概述
通过类的继承(派生)来引入 是一个 的关系 被继承的类——基类,继承的类——继承类。
#include <iostream>
using namespace std;
struct Base
{
};
struct Base2 : Base
{
};
struct Drive;
struct Drive : public Base2
{
};
int main()
{
Drive d;
Base& ref = d;
Base* ptr = &d;
}
使用基类的指针或引用可以指向派生类对象 静态类型 V.S. 动态类型 静态类型:编译器就可以确定的类型。 动态类型:在运行期为ref或者指针赋予的实际的类型。
#include <iostream>
using namespace std;
struct Base
{
void fun() {}
};
struct Base2 : public Base
{
};
struct Drive : public Base2
{
void fun2() {}
};
struct Drive2 : public Base2
{
};
int main()
{
Drive d;
Base& ref = d;
ref.fun();
Drive d2;
Base* ptr = &d;
ptr = &d2;
}
protected 限定符:派生类可访问
#include <iostream>
using namespace std;
struct Base
{
protected:
void fun() {}
int x;
};
struct Derive : public Base
{
public:
void fun2()
{
fun();
x;
}
};
int main()
{
Derive d;
Base b;
d.fun2();
}
类的派生会形成嵌套域
派生类中的名称定义会覆盖基类
#include <iostream>
using namespace std;
struct Base
{
int val = 2;
};
struct Derive : public Base
{
public:
void fun2()
{
cout << val << endl;
}
};
int main()
{
Derive d;
Base b;
d.fun2();
cout << d.val << endl;
}
使用域操作符显式访问基类成员
#include <iostream>
using namespace std;
struct Base
{
int val = 2;
};
struct Derive : public Base
{
public:
void fun2()
{
cout << val << endl;
cout << Base::val << endl;
}
int val = 3;
};
int main()
{
Derive d;
Base b;
d.fun2();
}
在派生类中调用基类的构造函数
#include <iostream>
using namespace std;
struct Base
{
Base ()
{
cout << "Base constructor is called" << endl;
}
};
struct Derive : public Base
{
public:
Derive ()
{
cout << "Derive constructor is called" << endl;
}
};
int main()
{
Derive d;
}
#include <iostream>
using namespace std;
struct Base
{
Base (int)
{
cout << "Base constructor is called" << endl;
}
};
struct Derive : public Base
{
public:
Derive (int a)
: Base(a)
{
cout << "Derive constructor is called" << endl;
}
};
int main()
{
Derive d(100);
}
虚函数
通过虚函数与引用(指针)实现动态绑定 使用关键字 virtual 引入 非静态、非构造函数可声明为虚函数 虚函数会引入vtable结构
#include <iostream>
using namespace std;
struct Base
{
virtual void baseMethod() {}
int baseMember;
};
struct myClassDerive : public Base
{
virtual void deriveMethod() {}
int deriveMember;
};
struct myClassDerive2 : public myClassDerive
{
virtual void deriveMethod2() {}
int deriveMember2;
};
int main()
{
myClassDerive2 d;
Base& b = d;
Base* ptr = &d;
myClassDerive2& d2 = dynamic_cast<myClassDerive2&>(b);
myClassDerive2* ptr2 = dynamic_cast<myClassDerive2*>(ptr);
}
如果我们想把一个基类的指针转成一个派生类的指针,如果基类的指针确实指向派生类的地址,那么这个转换就是成功的,否则指向空指针。基类的引用转换成派生类的引用,如果基类引用确实绑定在派生类的引用,就是成功的,否则抛出异常。
static_cast是在编译期处理的,但是dynamic_cast是在运行期发生的,判断动态类型能不能发生转变。如果要编写高性能的程序,dynamic_cast慎用。
#include <iostream>
using namespace std;
struct Base
{
virtual void fun()
{
cout << "Base :fun() is called" << endl;
}
};
struct Derive : Base
{
void fun()
{
cout << "Derive :fun() is called" << endl;
}
};
int main()
{
Derive d;
d.fun();
Base& b = d;
b.fun();
}
虚函数在派生类中的重写( override )
#include <iostream>
using namespace std;
struct Base
{
virtual void fun()
{
cout << "Base :fun() is called" << endl;
}
};
struct Derive : Base
{
void fun()
{
cout << "Derive :fun() is called" << endl;
}
};
void proc(Base& b)
{
b.fun();
}
int main()
{
Derive d;
proc(d);
Base b;
proc(b);
}
函数签名保持不变(返回类型可以是原始返回指针 / 引用类型的派生指针 / 引用类型)
#include <iostream>
using namespace std;
struct Base2 {};
struct Derive2 : Base2 {};
struct Base
{
virtual Base2& fun()
{
cout << "Base :fun() is called" << endl;
static Base2 b;
return b;
}
};
struct Derive : Base
{
Derive2& fun()
{
cout << "Derive :fun() is called" << endl;
static Derive2 inst;
return inst;
}
};
void proc(Base& b)
{
b.fun();
}
int main()
{
Derive d;
proc(d);
Base b;
proc(b);
}
可以通过 = 0 声明纯虚函数,相应地构造抽象基类 虚函数特性保持不变 override 关键字
继承与特殊成员函数
补充知识
|