1.继承:除了构造函数和析构函数,其他的一切都可以继承
不管是什么继承(公有,保护,私有)都能将父类的数据成员继承下来。例如下面程序:当仅有一个类A时或者一个类B时,其的大小为8字节,而当派生类B继承了基类A后,类B的大小为16字节。
继承的作用: (代码复用) 实现多态。
2.谁能访问,谁不能访问:
研究继承 分为两方面 : 继承的子类角度(类的内部) 和 站在对象的角度
在子类中:公有,保护和私有继承都可以访问父类的公有部分和保护部分,私有的(不管什么继承)不可访问。
在对象角度:公有继承,可以访问公有部分,保护和私有继承, 不可访问父类公有部分;站在对象的角度,唯一能访问的是公有的数据。
class A //基类
{
public:
void fun()
{
cout << “A::fun()” << endl;
}
protected:
void show()
{
cout << “A::show()” << endl;
}
private:
void list()
{
cout << “A::list()” << endl;
}
private:
int x;
int y;
};
class B : protected A //protected A//public A //派生类
{
public:
void print()
{
cout << “B::print()” << endl;
}
protected:
void print1()
{
}
private:
void print2()
{
}
private:
int a;
int b;
};
int main()
{
B b;
b.fun();
b.print();
//cout << sizeof(A) << endl; // 8
// cout << sizeof(B) << endl; // 16
return 0;
}
3.继承中若不表面什么形式的继承,那么都会默认成私有继承
构造过程中先构造父类,在构造子类。
构造顺序只和继承顺序有关,和初始化顺序无关。
先构造父类,在构造自身的对象成员,最后构造自身
class B1
{
public:
B1()
{
cout << “Create B1 Object.” << endl;
}
~B1()
{
cout << “Free B1 Object.” << endl;
}
};
class B2
{
public:
B2()
{
cout << “Create B2 Object.” << endl;
}
~B2()
{
cout << “Free B2 Object.” << endl;
}
};
class B3
{
public:
B3()
{
cout << “Create B3 Object.” << endl;
}
~B3()
{
cout << “Free B3 Object.” << endl;
}
};
class C : public B1, public B2, public B3 //构造顺序与继承顺序有关
{
public:
C():B1(), B3(), B2() //与初始顺序无关
{
cout << “Create C object.” << endl;
}
~C()
{
cout << “Free C Object.” << endl;
}
};
int main()
{
C c;
return 0;
}
4.虚继承:钻石继承;
不同来源的路线希望父类的值在子类里面只保留一个,这种手段就是虚继承。
如果,不添加virtual关键字,则会产生二异性,对象访问时,不知道访问哪个派生类继承的基类数据。
class B1
{
public:
B1()
{
cout << “Create B1.” << endl;
}
~B1()
{
cout << “Free B1.” << endl;
}
public:
int x;
};
class A1 : virtual public B1 //虚继承 B1为虚基类
{
public:
int a1;
};
class A2 : virtual public B1 //虚继承
{
public:
int a2;
};
class C : public A1, public A2
{
public:
int c;
};
int main()
{
C cc;
cc.c = 10;
//cc.x = 100; //会产生二异性,
//cc.A1::x = 100; //访问A1的x值
return 0;
}
5.同名隐藏;
如果子类和父类有同名的函数,那么子类会将父类的函数隐藏;
隐藏:指派生类的函数屏蔽了与其同名的基类函数;
规则:
(1)如果派生类的函数与基类的函数同名,但是参数不同,此时,不论有无virtual关键字,
基类的函数将被隐藏(注意别与重载混淆)
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字,
此时,基类的函数被隐藏(注意别与覆盖混淆)
6.复制兼容规则:
(1)把(派生类)子类的对象赋值给基类(父类)的对象 , 这时把派生类对象中从对位基类中继承来的隐藏对象赋值给基类对象。反过来不行,因为派生类的新成员无值可赋。
(2)将子类的对象的地址赋值给其父类的指针变量,但只能通过这个指针访问子类中由父类继承来的隐藏对象,不能访问派生类中的新成员。同样不能反过来。
(3)可以把子类的对象初始化父类的引用,引用时别名,但这个别名只能包含子类对象中的由基类继承来的隐藏对象。
子类隐藏包含了一个父类的对象,不管是通过对象还是指针以及引用,
都只能看到父类的范围,其他范围看不到
class B
{
public:
virtual void fun()
{
cout << “B::fun()” << endl;
}
void fun(int a)
{
cout << “B::fun(int)” << endl;
}
private:
int x;
};
class D : public B
{
public:
void fun() //同名覆盖;
{
cout << “D::fun()” << endl;
}
};
int main()
{
B b;
D d;
//1
b = d;
//2
B *pb = &d;
pb->fun();
//pb->list(); //父类的指针只能观察到父类的范围,子类多出来的成员看不到
//3
B &rb = d;
rb.fun();
//b.fun();
//b.fun(1);
//d.fun(); //访问子类
return 0;
}
4.怎么达到多态:
首先父类的方法是个虚方法,子类要重写这个方法,
重写的条件要达到三同:名字相同,返回值相同,参数列表相同
多态:相同的代码实现不同的功能(一个函数可以实现多个类的应用)。
纯虚方法:
定义:是指被标明为不具体实现的虚拟成员函数,它用于这样的情况:
定义一个基类时,会遇到无法定义基类中的虚函数的具体实现,其实现依赖于不同的派生类
格式: virtual 返回类型 函数名(参数列表)= 0;
含有纯虚函数的基类是不能够定义对象的。纯虚函数没有实现部分,不能产生对象,所以含有纯虚函数的类是抽象的。
抽象基类的作用是用来表示接口的定义;
抽象基类的子类必须将接口全部实现,没有实现则没有资格称为该基类
class A //A 代表动物,是一个抽象基类
{
public:
virtual void Eat()
{
cout << “A::Eat()” << endl;
}
virtual void Sleep()
{
cout << “A::Sleep()” << endl;
}
virtual void Foot()
{
cout << “A::Foot()” << endl;
}
};
class Dog : public A
{
public:
virtual void Eat()
{
cout << “Dog::Eat()” << endl;
}
virtual void Sleep()
{
cout << “Dog::Sleep()” << endl;
}
virtual void Foot()
{
cout << “Dog::Foot()” << endl;
}
};
class Cat : public A
{
public:
virtual void Eat()
{
cout << “Cat::Eat()” << endl;
}
virtual void Sleep()
{
cout << “Cat::Sleep()” << endl;
}
virtual void Foot()
{
cout << “Cat::Foot()” << endl;
}
};
class Bird : public A
{
public:
virtual void Eat()
{
cout << “Bird::Eat()” << endl;
}
virtual void Sleep()
{
cout << “Bird::Sleep()” << endl;
}
virtual void Foot()
{
cout << “Bird::Foot()” << endl;
}
public:
virtual void Fly()
{
cout << “Bird::Fly()” << endl;
}
};
class Ostrich : public Bird //鸵鸟
{
private:
virtual void Fly(); //因为鸵鸟不会飞,所以直接将其设为私有,不允许访问。
};
void Active(A *pa)
{
pa->Eat();
pa->Foot();
pa->Sleep();
}
int main()
{
Dog d;
Cat c;
Active(&c);
return 0;
}