向上转换和向下转换:
-
向上转换(Upcasting):将派生类指针或引用转换为基类指针或引用。这总是安全的,因为派生类包含基类的所有内容。具体说,转换为基类后,只能访问基类成员,而派生类又一定会有基类所有内容,所以安全。
- 基类指针可以指向基类对象与派生类对象,因为基类指针只能访问基类成员,而不管指向基类还是派生类,都能访问到基类成员。
-
向下转换(Downcasting):将基类指针或引用转换为派生类指针或引用。这可能不安全,因为基类指针可能实际上并不指向一个派生类对象(可能指向基类对象)。
- 根本原因是,基类指针可能指向基类对象或派生类对象
- 指向基类的话,如果能让你直接转换为派生类指针,程序员就容易犯罪了,真转了的话,该指针能够访问派生类的额外内容,但基类并没有这些内容,所以会有问题。
- 指向派生类对象的话还好说,指针转换为派生类的话,想访问额外内容也确实可以访问。
- 反正转换的时候用Dynamic_cast,如果该基类指针指向了基类指针,会转换失败,就直接自动指向空指针了。如果指向的是派生类,那成功。
- 根本原因是,基类指针可能指向基类对象或派生类对象
指针类型的作用
a) 类型安全:编译器可以检查指针操作是否合法。 b) 内存解释:告诉编译器如何解释指针指向的内存。 c) 指针算术:不同类型的指针在进行加减操作时步长不同。 d) 函数重载:允许基于指针类型进行函数重载。
指针类型主要是一个编译时的概念。在运行时,CPU只看到内存地址,不关心类型。
这个构造函数接受一个 const
引用参数 rhs
,它表示将要被拷
贝的对象。该构造函数做了以下工作:
- 首先,它通过使用基类的构造函数来初始化自身(
Base(rhs)
) 。 - 然后,它分配内存来保存
_pderived
的拷贝(_pderived = new char[strlen(rhs._pderived) + 1]()
)。注意,这里使用了动 态内存分配(new[]
)和strlen
函数。 - 最后,它通过
strcpy
将rhs._pderived
的内容复制到_pderived
中。
这个构造函数的目的是复制 rhs
对象中的所有成员,并将其作为
新的对象返回。
赋值运算符
Derived & operator=(const Derived & rhs){
cout << "Derived & operator=(const Derived &)" <<
endl;
if(this != &rhs){
//显式调用基类的赋值运算符函数
Base::operator=(rhs);//关键
delete [] _pderived;
_pderived = new char[strlen(rhs._pderived) + 1]();
strcpy(_pderived,rhs._pderived);
_derived = rhs._derived;
}
return *this;
}
这个赋值运算符函数接受一个 const
引用参数 rhs
,它表示要
被赋值的对象。该函数做了以下工作:
- 首先,它检查是否
this
和rhs
是指向同一个对象。如果是 ,则返回当前对象(return *this;
)。 - 然后,它通过使用基类的赋值运算符函数来初始化自身(
Base::operator=(rhs)
)。注意,这里显式地调用了基类的赋值运 算符函数。 - 接下来,它释放
_pderived
中的旧数据,并重新分配新的内存 空间(delete [] _pderived; _pderived = new char[strlen(rhs._pderived) + 1]()
)。 - 最后,它通过
strcpy
将rhs._pderived
的内容复制到_pderived
中,然后赋值_derived
到其对应的成员。
这个赋值运算符函数的目的是将 rhs
对象中的所有成员赋值给当
前对象,并返回当前对象本身。
基类成员 | Public继承 | Protected继承 | Private继承 |
---|---|---|---|
Public | Public | Protected | Private |
Protected | Protected | Protected | Private |
Private | 不可访问 | 不可访问 | 不可访问 |