先写一个父子类AB
class A
{};
class B : public A
{};
class Member
{
public:
virtual A* f() //虚函数的返回值必须是一个父子类的指针或引用
{
return new A;
}
};
class Student : public Member
{
public:
virtual B* f() //虚函数的返回值必须是一个父子类的指针或引用
{
return new B;
}
};
class Member {
public:
virtual ~Member()
{
cout << "~Member()" << endl;
}
};
class Student : public Member {
public:
~Student() // 自动成为虚析构(无需显式写virtual)
{
cout << "~Student()" << endl;
}
};
// 只有派生类Student的析构函数重写了Person的析构函数,下面的delete对象调用析构函
//数,才能构成多态,才能保证p1和p2指向的对象正确的调用析构函数。
int main()
{
Member* p1 = new Member;
Member* p2 = new Student;
delete p1;
delete p2;
return 0;
}
结果如下:
一道难题
c复制代码
class A
{
public:
virtual void func(int val = 1)
{
std::cout << "A->" << val << std::endl;
}
virtual void test() { func(); }
};
class B : public A
{
public:
void func(int val = 0)
{
std::cout << "B->" << val << std::endl;
}
};
int main()
{
B* p = new B;
p->test();
return 0;
}
类 A 的定义 : virtual void func(int val = 1):虚函数func,默认参数为 1,输出A->val。 virtual void test() { func(); }:虚函数test,内部调用func()。 类 B 的定义 : void func(int val = 0):重写基类A的虚函数func,默认参数改为 0,输出B->val。 注意 :B没有重写test函数 ,因此test仍使用基类A的实现。 main 函数执行流程 : B* p = new B;:创建B类型对象,指针p的静态类型是B*,实际类型也是B。 p->test();:调用test函数: 第一步 :test函数未被B重写,因此执行基类A的test函数。 第二步 :A的test中调用func(),由于func是虚函数,动态绑定到实际对象类型(B)的func,因此执行B::func。 第三步 :func的默认参数遵循静态绑定(由调用点的静态类型决定):test属于A类,因此默认参数使用A::func的1,而非B::func的0。 最终输出:B->1。
C++11 override和final
final:修饰虚函数,表示该虚函数不能再被重写
c复制代码
class A
{
public:
virtual void func() final
{
cout << "A" << endl;
}
};
class B : public A
{
public:
virtual void func()//出错,不允许重写
{
cout << "B" << endl;
}
};
例子:实现一个类,让这个类不能被继承
c复制代码
//法一:将构造函数私有化
class A
{
public:
int _a;
private://将构造函数私有,派生类的构造,必须调用基类的构造,这里继承过去不可见,无法调用
A(){}
};
class B :public A
{
};
int main()
{
B bb;
}
final:修饰类,这个类不能被继承
c复制代码
//法二:类后加final成为最终类
class A final//加final关键字,final修饰的类为最终类,不能被继承
{
public:
int _a;
};
class B : public A//出错
{
};
override:检查派生类虚函数是否重写了基类的某个虚函数,如果没有重写编译报错
c复制代码
class A
{
public:
virtual void func()
{
cout << "A" << endl;
}
};
class B : public A
{
public:
virtual void func() override//加在派生类的某个虚函数
{
cout << "B" << endl;
}
};
class Car//抽象类
{
public:
virtual void Drive() = 0;//纯虚函数
};
int main()
{
Car c;//出错
return 0;
}
例子:抽象类的一种使用方式
c复制代码
class Car//抽象类
{
public:
virtual void Drive() = 0;//纯虚函数
};
//间接强制了子类重写虚函数,因为不重写的话,子类依旧是抽象类,不能实例化出对象
class Benz :public Car
{
public:
virtual void Drive()
{
cout << "Benz-舒适" << endl;
}
};
class BMW :public Car
{
public:
virtual void Drive()
{
cout << "BMW-操控" << endl;
}
};
int main()
{
//Car* a = new Benz;普通调用
//a->Drive();
//Car* b = new BMW;普通调用
//b->Drive();
Car* a = new Benz;//多态调用
a->Drive();
Car* b = new BMW;//多态调用
b->Drive();
return 0;
}
class A
{
public:
virtual void funca1() { cout << "A::funca1" << endl; }
virtual void funca2() { cout << "A::funca2" << endl; }
virtual void funca3() { cout << "A::funca3" << endl; }
public:
int a;
};
class B :virtual public A
{
public:
int b;
};
class C :virtual public A
{
public:
int c;
};
class D :public B, public C
{
public:
int d;
};
int main()
{
D dd;
dd.B::a = 1;
dd.C::a = 2;
dd.b = 3;
dd.c = 4;
dd.d = 5;
return 0;
}
分析如下:
例子2
c复制代码
class A
{
public:
virtual void func1() { cout << "A::func1" << endl; }
virtual void func2() { cout << "A::func2" << endl; }
virtual void func3() { cout << "A::func3" << endl; }
public:
int a;
};
class B :virtual public A
{
public:
virtual void func1() { cout << "B::func1" << endl; }
public:
int b;
};
class C :virtual public A
{
public:
virtual void func2() { cout << "C::func2" << endl; }
public:
int c;
};
class D :public B, public C
{
public:
virtual void func1() { cout << "D::func1" << endl; }
public:
int d;
};
int main()
{
D dd;
dd.a = 1;
dd.b = 2;
dd.c = 3;
dd.d = 4;
return 0;
}
如上类B对类A的func1进行了重写,类C对类A的func2进行了重写,而类D对类B的func1进行了重写。 B、C 只是重写了 A 的虚函数(比如 B 重写 A 的 func1),这些重写的函数可以共享虚基类 A 的虚函数表(因为 A 的虚表会记录最终覆盖后的函数地址)。
例子3
c复制代码
class A
{
public:
virtual void func1() { cout << "A::func1" << endl; }
virtual void func2() { cout << "A::func2" << endl; }
virtual void func3() { cout << "A::func3" << endl; }
public:
int a;
};
class B :virtual public A
{
public:
virtual void func4() { cout << "B::func4" << endl; }
virtual void func5() { cout << "B::func5" << endl; }
public:
int b;
};
class C :virtual public A
{
public:
virtual void func6() { cout << "C::func6" << endl; }
virtual void func7() { cout << "C::func7" << endl; }
public:
int c;
};
class D :public B, public C
{
public:
virtual void func8() { cout << "D::func8" << endl; }
virtual void func9() { cout << "D::func9" << endl; }
public:
int d;
};
int main()
{
D dd;
dd.a = 1;
dd.b = 2;
dd.c = 3;
dd.d = 4;
return 0;
}
现在给 B 加了func4、func5,给 C 加了func6、func7------ 这些是A 没有的独有的虚函数,无法存到 A 的虚函数表里,所以 B、C 必须各自有一个自己的虚函数表指针(vfptr),指向自己的虚函数表(用来存这些独有的虚函数地址)。
class A
{
public:
virtual void func1(){}
public:
int a;
};
class B:public A
{
public:
virtual void func2(){}
public:
int b;
};
class C :public B
{
public:
virtual void func3() {}
public:
int c;
};
int main()
{
C cc;
cc.a = 1;
cc.b = 2;
cc.c = 3;
return 0;
}