类的访问控制和继承
类的静态成员
类的静态成员用关键字static
修饰,类似静态变量或静态函数,也是有共享的概念
类的静态变量:
静态变量在类的所有对象中共享,不能再类的定义中初始化,但可以在类外部通过作用域符::
来初始化,或通过对象初始化
class box{
public:
static int a;
};
int box::a=2;
int main(){
box b1;
cout<<b1.a;
}
静态变量也是有作用域的,需要public
,调用时,只能通过对象调用,不能直接用类调用
静态成员函数:
类的静态成员函数可以直接被类调用,不需要初始化对象
class box{
public:
static void print(){};
};
int main(){
box::print();
}
和普通成员函数的区别:
-
静态成员函数没有this指针,只能访问静态成员
-
而普通成员函数可以访问所有的,包括静态和非静态的成员
类中特殊成员变量的初始化:
-
const常量:必须通过构造函数参数列表初始化
-
引用变量:必须通过构造函数参数列表初始化
-
普通静态变量:要在类外通过
::
初始化 -
静态整型常量:就是
static const int
,可以在定义的时候直接初始化 -
静态非整型常量:要在类外通过
::
初始化
访问控制范围和继承范围
访问范围:
访问 | public | protected | private |
---|---|---|---|
同一个类 | yes | yes | yes |
派生类 | yes | yes | no |
外部的类 | yes | no | no |
一个派生类继承所有基类的方法,除了:
-
基类的构造函数,析构函数和拷贝构造函数
-
基类的重载运算符
-
基类的友元函数
-
而且,派生类不能用初始化列表去初始化基类的成员,只能在函数体中初始化
继承范围:
继承方式 | 基类的public成员 | 基类的protected成员 | 基类的private成员 |
---|---|---|---|
public继承 | 仍为public成员 | 仍为protected成员 | 不可见 |
protected继承 | 变为protected成员 | 变为protected成员 | 不可见 |
private继承 | 变为private成员 | 变为private成员 | 不可见 |
c++支持多继承:一个子类可以有多个父类
环状继承:A->D,B->D,C->A,B
这样的继承会使D创建两个对象,如:
#include<iostream>
using namespace std;
class box{
public:
box(){cout<<"create object"<<endl;};
};
class A:public box{};
class B:public box{};
class C:public A,public B{};
int main(){
C c1;
}
要解决上面的问题就要用虚拟继承
格式:class 类名:virtual 继承方式 父类名
class A:virtual public box{};
class B:virtual public box{};
class C:public A,public B{};
上面说了,派生类不继承基类的构造函数,但是可以通过初始化列表调用基类的构造函数来初始化
#include<iostream>
using namespace std;
class box{
public:
int a;
box();
box(int a){this->a=a;};
};
class square:public box{
public:
square(int a):box(a){};
};
int main(){
square s(23);
cout<<s.a;
}
使用square(int a):box(a){};
调用了基类的构造函数.
派生类继承的成员和本身的成员重名的话,不会覆盖或冲突,因为继承过来变量和本身的变量在不同的内存空间
如:
#include<iostream>
using namespace std;
class box{
public:
int a;
void setA(int a){this->a=a;};
};
class square:public box{
public:
int a;
void setAA(int a){this->a=a;};
};
int main(){
square s;
s.setA(10);
s.setAA(20);
cout<<s.box::a<<endl;
cout<<s.square::a;
}
可以用作用域符::
访问不同的同名变量