最近学习c++多态和继承方面的东西,写下来方便记忆,欢迎指正
#include <iostream>
#include <string>
using namespace std;
class Base{
public:
int a;
static int b;//在类中声明的static变量必须在类外部再定义一次!,否则无法被调用.在类内不能初始化static成员(除了const成员),只能在类外
Base()
{
abc te;
a = 15;
te.i = 10;
}
class abc{
public:
int i;
};
//函数不能同时为virtual和static
virtual void test(){ cout << "this is parent test" << endl; }//基类一旦声明为虚函数,且子类对此函数均为重写
//当用基类对象访问此函数时,会转到子类定义的函数中.
void test1(){ cout << "this is parent test1" << endl; }
virtual int glh() = 0;//纯虚函数必须在子类中实现
//static函数是全局类的函数,由于函数不能同时为virtual和static,所以static函数不能被重写
static void read() { cout << "this is parent read,value is " << b++ << endl; }//static函数在类内部或外部定义均可
};
int Base::b = 88;//必须在类外再次定义,并可以初始化
//void Base::read(){ cout << "this is parent read,value is " << b << endl; }//static函数只能访问static成员变量
class Derived :public Base{
public:
Derived()
{
a = 19;
}
virtual void test(){//这里不管加不加virtual,base->test();都会执行到这里,但是参数类型和数量和返回类型必须与基类的函数相同,否则相当于重新定义了一个函数
cout << "this is Derived son test" << endl;}//如果注释掉此函数,则基类指针会调用基类的base->test();
void test(string &str){ cout << "this is Derived son test,value is " << str << endl; }//此函数不能被基类直接访问到
void test1(){ cout << "this is Derived son test1" << endl; }//此函数不能被基类直接访问到,如果注释掉此函数,那么sobase.test1();
//会被报错,因为子类定义的同名函数void test1(string &str)(不管参数相不相同,只要函数名相同,子类即覆盖了继承自基类对应的函数),如果想
//访问基类的test1,一.将void test1(string &str)注释掉,防止覆盖;二.
void test1(string &str){ cout << "this is Derived son test1,value is " << str << endl; }//此函数不能被基类直接访问到
static void read(){ cout << "this is son read,value is " << b++ << endl; }//在子类可以重载基类static函数,但同样无法使用基类指针访问
void write(){ cout << "this is son write" << endl;}
int glh(){ a = 3; return 1; }
};
//总结:如果子类想通过基类指针访问自己定义的函数,那么需要将基类的对应函数声明称virtual重写此函数,但是此指针是无法访问子类其余的重载函数,如
//Derived的test1(),只能通过子类的对象进行访问.
//为什么要把子类的指针赋值给父类?如Base *base = &sobase;
//我个人估计一年或者几年之后你又会问“如何隐藏类的定义,让用户看不到类的实现细节”或者“如何让用户无法修改类的私有成员”。
//一个办法就是用子类型多态。
//在父类定义所有需要用到的接口(公共成员函数)和允许用户看到的数据,把父类暴露给用户。而在子类中定义实现细节,用户不知道子类的定义——甚至
//不知道子类叫什么名字,将来哪怕完全替换掉子类的实现,换成另一个子类,用户也会一无所知。最后需要做的就是写一个函数来返回“子类指针”了
//——因为我们不想让用户知道子类的任何信息,所以函数不能不能直接声明成返回子类对象或者返回“子类指针”,正确的做法是声明成返回父类指针,
//而实际上,却是把子类指针转换成父类指针然后返回.这就是virtual的用处了.
int main()
{
int n;
string str("python");
Derived sobase;
Base *base = &sobase;
cout << base->a << endl;//19
base->test();//this is Derived son test
base->test1();//this is parent test1,同下
base->read();//b == 88
//base->test1(str);//如果在子类中重载基类的函数,那么使用基类的指针是无法访问此重载函数的,编译器报错
sobase.test1();//如果想访问子类重载基类的函数,必须用子类的对象去访问
sobase.test1(str);//如果想访问子类重载基类的函数,必须用子类的对象去访问
sobase.read();//b == 89
Derived ssbase;
ssbase.read();//b == 90,可以看出b是全局的,不随对象的变化而变化
return 0;
}