1、C++单冒号的含义

(1)类后冒号,表示继承

【类名:public 类名】

//单继承
class A:public B
B是基类,A是B的派生类,即类A按public模式继承类B。
//多继承
class A:public B, public C

继承的三种模式(public,protected,private),以小范围为准。
若是public继承,则public和protected成员分别被继承为子类的public和protected成员,若是protected继承,则public和protected成员均被继承为子类的protected成员。private继承,则public和protected成员均被继承为子类的private成员。
《C++规范》:规则6.9 使用public继承而不是protected/private继承

(2)冒号后面,表示括号赋值

【变量类型:变量名(赋的值)】

// 在程序中定义变量并初始化的机制中,有两种形式,一个是我们传统的初始化的形式,即赋值运算符赋值,还有一种是括号赋值,如:
char b='r';//赋值运算符赋值
char b('r');//括号赋值

注意:括号赋值只能变量定义并初始化中,不能用在变量定义后再赋值。

【函数名(形参名):变量名(形参名)】

A(int aa, int bb):a(aa),b(bb){}
相当于
A(int aa, int bb)
{
 a=aa;
 b=bb;
}

(3)构造函数定义时,后的冒号,表示初始化列表

【类名::构造函数(形参表):变量名(变量的初始化参数){函数体}】

//函数定义时,后加一个冒号,表示使用初始化列表来初始化字段
Line::Line(double len): length(len)  // 相当于length=len
{
  cout<<"Object is being created, length = "<<len<<endl;
}

//上面的语法等同于如下语法:
Line::Line(double len)
{
    length = len;
    cout << "Object is being created, length = " << len << endl;
}

//多个字段 X、Y、Z 初始化,逗号分隔
C::C(double a, double b, double c):X(a), Y(b), Z(c){...} 
// 相当于X=a,Y=b,Z=c

四种情况下应该使用初始化表达式来初始化成员:
1:初始化const成员
2:初始化引用成员
3:当调用基类的构造函数,而它拥有一组参数时
4:当调用成员类的构造函数,而它拥有一组参数时。

为什么要冒号后初始化?
C++":"后初始化的机制,使引用和常量数据成员变为可能的

解释
class Student
{
  public :
    Student()
  protected:
    const int a;
    int &b;
}

Student::Student(int i,int j)
{
  a=i;
  b=j;
}
    在Student类中有两个数据成员,一个是常量数据成员,一个是引用数据成员,并且在构造函数中初始化了这两个数据成员,但是这并不能通过编译,因为常量初始化时必须赋值,它的值是不能再改变的,与常量一样引用初始化也需要赋值,定义了引用后,它就和引用的目标维系在了一起,也是不能再被赋值的。所以C ++":"后初始化的机制,使引用和常量数据成员变为可能的,Student类的构造函数应为:
Student::Student(int i,int j):a(i),b(j)
{
}

(4)构造函数使用时,后面的冒号表示初始化【其实还是初始化】

【B的构造函数名(参数表):A的构造函数名(参数表)】

class A
{
  public:
    int x;
    A(int a=0){x=a};
};
class B1:publicA
{
  public:
    int y1;
    B1(int a=0,int b=0):A(b)  //就是这句
    { y1=a; }
};

请问那句后面的“:A(b)”代表什么啊,为什么要跟在B1基类的构造函数后面?
答:A(b)实际上是做的是用b初始化A的成员x;即x=b; 是初始化列表方式。

参考:
https://www.cnblogs.com/muyi23333/articles/13515792.html

2、C++双冒号::含义(范围解析运算符)

(1)作用域分解运算符

【返回值 类名::成员函数名(参数表){函数体}】

// 类的成员函数定义,一般用于在.h文件中声明函数,在.c文件中定义函数。
int A::add(int a, int b){return a+b;} // 用::定义

class A{ //声明
public:
  int a_var;
  int add(int a, int b);
  int add(int a);
}

(2)类实例的成员(不带类名)

【::成员名】

int A::add(int a){
  return a+::a_var; // 当前类实例的成员变量
}

(3)类的成员

【类名::成员名】

A::a_var; //怎么用呢?

(4)全局作用域

【::全局变量名】

// 当全局变量和局部变量重名时,就用::表示全局变量,以区分。
int a;
void f(int a){
  int a = ::a;
}

(5)命名空间【不理解?】

参考:
https://blog.csdn.net/qq_42362891/article/details/116197294
https://blog.csdn.net/weixin_45525272/article/details/107482219

3、virtual

析构函数需要声明为virtual条件
当定义的类中析构函数外其他函数有virtual函数时,这时需要将此类的析构函数定义为virtual函数。

virtual析构函数好处
当父类指针指向子类对象时,执行释放操作,子类对象也会被释放掉

当定义析构函数为virtual函数时需要知道当前类是否还有子类,如果没有子类,则可以将其析构函数不定义为virtual函数,否则则定义为虚函数。

含有virtual的函数其对象的体积会增加,因为它多了一个vptr指针,所以C++的Point对象就不能和其他语言有着一样的声明结构了,因为也不再具有可移植性。

参考:
https://www.cnblogs.com/jiayouya-susu/p/11962694.html

10、术语

类的数据成员=类的成员变量
范围解析运算符 ::

posted on 2022-08-08 11:16  西伯尔  阅读(97)  评论(0编辑  收藏  举报