c++ 知识

c++知识

多个类的相互调用

类的相互调用,这篇博客讲的比较清晰
同时这篇博客和我之前的《c++类之间相互引用,c++友元类,c++类内互相有对方的指针 KartoSLAM代码为例》说的是同一个问题

继承与派生

c++派生与继承
重点:父类的private成员不可被派生类直接访问(那就是有别的方法访问,应该是由父类提供)

使用多态机制的时候,一般调用的函数都是 子类的函数
比如 class B : public A

A * a= new B;
a->run(); //这个实际上是 B的run
a->A::run();  //A的run

也可以用下面的方式使用A的run

B b;
b.A::run();

private public protected 区别

区别文章链接
protected 可以被子类访问,其他和private差不多

使用private继承,父类的所有方法在子类中变为private;
使用protected继承,父类的protected和public方法在子类中变为protected,private方法不变;
使用public继承,父类中的方法属性不发生改变;
public:可以被任意实体访问
protected:只允许子类及本类的成员函数访问
private:只允许本类的成员函数访问

深拷贝和浅拷贝

一篇博客
如果一个类拥有指针类型的成员变量,那么绝大部分情况下就需要深拷贝,因为只有这样,才能将指针指向的内容再复制出一份来,让原有对象和新生对象相互独立,彼此之间不受影响。如果类的成员变量没有指针,一般浅拷贝足以。

另外一种需要深拷贝的情况就是在创建对象时进行一些预处理工作,比如统计创建过的对象的数目、记录对象创建的时间等

静态成员变量初始化

重点博客

如果是 const static int 这种,注意一定 int\ bool\ char 等整型类型可以 用const + static修饰, 可以在类内直接写结果。
否则如果需要 static double ,就不能用const修饰了,而应该用 constexpr修饰,然后初始化。
https://blog.csdn.net/wphkadn/article/details/88174109 所指出的错误所示。

  • static 成员变量必须在类声明的外部初始化,
  1. 直接声明时就初始化静态成员变量,会出现编译错误"ISO C++ forbids in-class initialization of non-const static member",
  2. 如果在构造函数初始化静态成员变量,会出现undefined reference to Student::m.
  3. 如果不初始化,同样编译报错undefined reference to `Student::m
    具体形式为:
type class::name = value;
int Student::m_total = 0;

静态成员变量在初始化时不能再加 static,但必须要有数据类型。被 private、protected、public 修饰的静态成员变量都可以用这种方式初始化。
注意:static 成员变量的内存既不是在声明类时分配,也不是在创建对象时分配,而是在(类外)初始化时分配。反过来说,没有在类外初始化的 static 成员变量不能使用。

  • static 成员变量不占用对象的内存,而是在所有对象之外开辟内存,即使不创建对象也可以访问。.

静态成员函数

http://c.biancheng.net/view/2228.html
静态成员函数与普通成员函数的根本区别在于:
普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。

常成员变量与常成员函数

http://c.biancheng.net/view/2230.html

  • 对初始化只能使用初始化列表这句表述持怀疑态度
  • 实验结果, const修饰的不管是静态成员变量还是动态成员变量其实都是可以直接初始化的
public:
const int m = 0;
const static int m = 0;
const double m = 0.0;
const static double m=0.0; //错误, 需要用 constexpr替代const, 只有int\ bool\ char 等整型类型可以 用const static int
  • 对于 string 来说,无法用 static+const 或者 static+constexpr 修饰类内或者类外的string,因为 string的构造函数不是常量表达式
  • const函数的声明和定义里面都要使用const。

const对象

http://c.biancheng.net/view/2232.html
在 C++ 中,const 也可以用来修饰对象,称为常对象。一旦将对象定义为常对象之后,就只能调用类的 const 成员(包括 const 成员变量和 const 成员函数)了。

继承中的析构函数

class A
class B: public A
可以看到B继承了A,一般情况下A的析构函数要写成虚函数,这是为了指针考虑。

class *A = new B;
delete A.

如果A没有将析构函数定义为虚函数,那么delete A的时候就只会调用A的析构函数,因为指针只看到了基类
如果A的析构函数声明为虚函数,那么就能正常调用B的析构函数,这就是多态

当然如果你只定义对象,没有使用多态机制,那么就不会有这个问题。
不使用多态的例子
使用多态的例子

virtual

派生类重写的函数前面可以不加 virtual, 这取决于你是否还有其他类要集成这个派生类。 但通常加一个override是比较好的,这是用于说明这个函数是一个重写函数。 因为你可能在写函数名称或参数列表写错了,和父类不一样。但编译器并不知道你确实要重写父类的这个函数,所以编译通过,但实际上是不符合你的逻辑的。

  • 纯虚函数
    A类中定义了如下的虚函数,称之为纯虚函数
    virtual int run() = 0;
    这样的话,可以编译通过,但是你不能直接生成A的实例,你必须找一个派生类实现这个run函数,然后利用A *a = new B这种方式来声明一个A的对象,也就是说一个对象的函数必须都是有定义的。

函数重载

C++ 中的函数重载

在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。
例如

double run(int a)
int run(int a)   //错误
编译不通过,不能仅通过返回类型不一样来重载函数
int run(int a, int b, bool c)
int run(int b, bool c, int a) //正确
形式列表顺序不一样

运算符重载(包括 [] >> << (前置)++ (后置)++ == != 以及 * ->实现类似于iterator的操作)-

  • 实现iterator的操作还有很多细节部分,现在先不重载了,大概只记录下在c++ premier 5 的504页
  • 还有函数调用运算符 operator()(),
  • ostream 是输出类的内容,一般使用const,同时 ostream和 istream都返回 引用,istream是输出,所以不会使用const,这两个函数一般声明为友元函数
  • == != > < >= <= 一般均为bool
  • " + - " 一般返回同类型,而不是引用
  • = += -= ++ – 一般返回引用, 同时要定义成类的成员
  • [] 要返回引用,这样既能 把结果放在=左边来进行赋值,也能放在右边来获取
  • ++ - - 有前置后置之分, 前置返回引用,参数列表为空,后置返回同类型,参数列表写为int 。
#include <iostream>
#include <string>
using namespace std;

class A
{
private:
    int a;
    int b;
    int c;
public:
    A():a(1),b(2),c(3){}
    A(int a, int b, int c)
    {
        this->a=a;
        this->b=b;
        this->c=c;
    }
    friend ostream &operator<<(ostream &os, const A &A_);
    friend istream &operator>>(istream &is, A &A_);
    bool operator==(const A & b)
    {
        return this->a==b.a && this->b==b.b && this->c==b.c;
    }
    friend bool operator==(const A & b, const A & c)
    {
        return c.a==b.a && c.b==b.b && c.c==b.c;
    }
    bool operator!=(const A & b)
    {
        return !(*this==b);
    }
    int &operator[](std::size_t n)
    {
        if(n==0) return this->a;
        if(n==1) return this->b;
        if(n==2) return this->c;
    }

    A& operator++()
    {
        this->a++;
        return *this;
    }
    A operator++(int)
    {
        A tmp = *this;
        this->a ++;
        return tmp;
    }
    int operator()()
    {
        cout << "f" << endl;
        return 0;
    }
};
ostream &operator<<(ostream &os, const A &A_)
{
    os << A_.a << ' ' << A_.b <<' ' << A_.c ;
    return os;
}

istream &operator>>(istream &is, A &A_)
{
    is >> A_.a >> A_.b >> A_.c;
    if(!is)
        A_ = A();
    return is;
}

int main()
{
    A a;
    cout << a << endl;
    A b;
    A c;
    a++;
    cout << a << endl;
    cout << ++a <<endl;
    cout << a++ << endl;
    cout << a << endl;
    cout << a();
    cout << "endl" << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值