全文,遵循一个逻辑,具体示例思想:
车可以看作是一个基类,公交车可以看是一个车的派生类,我们可以说大巴车是(转换成)车,但绝对不能说车是(转换)大巴车,因为可能是小轿车,也可能是火车。
允许从下到上的转换,即将派生类对象赋予基类对象:
class Base {
public:
Base(int data) :ma(data) { cout << "Base(int data)" << endl; }
Base() = default;
~Base() { cout << "~Base()" << endl; }
protected:
int ma;
};
class Deriver :public Base {
public:
Deriver(int data) :mb(data), Base(data) { cout << "Deriver(int data)" << endl; }
~Deriver() { cout << "~Deriver()" << endl; }
private:
int mb;
};
- 基类对象赋值给派生类的对象: error
int main() {
Base b(99);
Deriver d(88);
//d = b;
return 0;
}
对象b、d内存如上图所示
d对象的内存布局由两部分组成,一部分是继承而来的基类部分,另一部分是自定义数据部分
b对象仅由自定义数据构成
当拿b给d赋值时,编译器知道用b的ma部分赋值给d的ma,但是剩余的d的部分编译器不知道该怎么处理怎么赋值,所以出错
- 派生对象赋值给基类的对象: success
int main() {
Base b(99);
Deriver d(88);
b = d;
return 0;
}
对象b、d内存如上图所示
当拿d给b赋值时,编译器用d的ma部分赋值给b的ma即可完成赋值。
- 基类指针指向派生类对象: success
class Base {
public:
Base(int data) :ma(data) { cout << "Base(int data)" << endl; mc = data; }
Base() = default;
~Base() { cout << "~Base()" << endl; }
int mc;
protected:
int ma;
};
class Deriver :public Base {
public:
Deriver(int data) :mb(data), Base(data) { cout << "Deriver(int data)" << endl; }
~Deriver() { cout << "~Deriver()" << endl; }
private:
int mb;
};
int main() {
Base b(99);
Deriver d(88);
Base* p = &d;
cout << p->mc << endl;
//cout << p->mb << endl;
return 0;
}
基类类型的指针p解引用只能访问类型为基类的内存,即对象d内存的基类部分,无法访问对象的派生类部分,这是由指针的类型决定.
- 派生类指针指向基类对象: error
int main() {
Base b(99);
Deriver d(88);
//Deriver* q = &b;
return 0;
}
指针q解引用只能访派生类类型的内存,即对象b内存的派生类部分,但是基类怎么可能有派生类的内存部分,这是也由指针的类型决定,所以失败.