在任何需要基类对象的地方都可以用公有派生类的对象来代替,这条规则称为赋值兼容规则。包括以下情况:
1.派生类的对象可以赋值给基类的对象,这时是把派生类对象中从对应基类中继承来的隐藏对象赋值给基类对象。反过来不行,因为派生类的新成员无值可赋。
2.可以将一个派生类对象的地址赋值给基类的指针变量,但只能通过这个指针访问派生类中由基类继承来的隐藏对象,不能访问派生类中的新成员。
3.派生类对象可以初始化基类的引用。引用是别名,但这个别名只能包含派生类对象中的由基类继承来的隐藏对象。
下面这个例子说明了上面几种情况:
class Person
{
private:
int value;
public:
Person(int x = 0) :value(x)
{
}
};
class Student : public Person
{
private:
int num;
public:
Student(int x=0):num(x),Person(x+10)
{
}
};
int main()
{
Person se(23);
Student st(10);
Person& ps = st;
Person* p = &st;
se = st;
return 0;
}
析构函数是由系统管理的,所以不需要标明是调用的子对象的析构函数还是父对象的析构函数,像构造函数还有拷贝构造函数等如果需要调动父对象的函数时都需要注明,如Object(base)这样。
先调动子对象的析构函数再调动父对象的析构函数,先调动父对象的构造函数后调用子对象的构造函数。
接下来我们介绍同名隐藏的内容:
class Object
{
public:
int value;
public:
Object(int x=0):value(x){}
};
class Base :public Object
{
public:
int value;
public:
Base(int x=0):Object(x),value(x+10){}
void Set()
{
value = 10;
Object::value=100;//指明操作父类中的value
}
};
在这个代码中,我们可以看到父类和子类中都有一个名为value的成员属性,在子类中的Set方法中操纵的是Base中的value,依靠的是就近原则,此时将父类Object中的value隐藏了,这就叫做同名隐藏的概念。
如果想对父类中的value进行操作,必须要用“::”指明。
再来看下面这个将父类中的成员方法隐藏了的例子,此时也必须用“::”作用域解析符指明调用父类中的成员方法才可以调用,否则就将其隐藏。
class Object
{
public:
int value;
public:
Object(int x = 0) :value(x) {}
void Print() const
{
cout << value << endl;
}
};
class Base :public Object
{
public:
int num;
public:
Base(int x=0):Object(x),num(x+10){}
void Print() const
{
cout << num << endl;
}
};
int main()
{
Base base1(10);
base1.Print();//调用子对象的Print
base1.Object::Print();//调用父对象的Print
return 0;
}
再看下面这两个例子: