C++继承可以是单一继承或多重继承,每一个继承连接可以是public,protected,private也可以是virtual或non-virtual。然后是各个成员函数选项可以是virtual或non-virtual或pure virtual。本文仅仅作出一些关键点的验证。
public继承,例如下:
class base { ...... }; class derived:public base //子类 { ...... };
如果这样写,编译器会理解成类型为derived的对象同时也是类型为base的对象,但类型为base的对象不是类型为derived的对象(金鱼是鱼,但是是鱼的不一定就是金鱼)。这点很重要。那么函数形参为base类型适用于derived,形参为derived不适用于base。下面是验证代码,一个参数为base的函数,传入derived应该成功执行,相反,一个参数为derived的函数
#include <iostream> #include <stdio.h> #include <string> class base { public: base()//无参构造函数 :baseName(""),baseData(0)//成员初始化 {} base(std::string bn,int bd)//带参构造函数 :baseName(bn),baseData(bd) //成员初始化 {} std::string getBaseName() const { return baseName; } int getBaseData()const { return baseData; } private: std::string baseName; int baseData; }; class derived:public base //子类 { public: derived():base(),derivedName("") {} derived(std::string bn,int bd,std::string dn) :base(bn,bd),derivedName(dn) //子类构造函数中显示调用父类的构造函数 {} std::string getDerivedName() const { return derivedName; } private: std::string derivedName; }; void show(std::string& info,const derived& b) { info.append("Name is "); info.append(b.getBaseName()); info.append(", baseData is "); char buffer[10]; sprintf_s(buffer,"%d",b.getBaseData());//VS2012用sprintf报错 info.append(buffer); } int main(int argc,char* argv[]) { base b("test",10); std::string s; show(s,b); std::cout<<s<<std::endl; derived d("btest",5,"dtest"); std::string ss; show(ss,d); std::cout<<ss<<std::endl; return 0; }
运行结果为:
Name is test, baseData is 10
Name is btest, baseData is 5
请按任意键继续. . .
下面改改代码,将show()函数参数变为derived
void show(std::string& info,const derived& b) { info.append("Name is "); info.append(b.getBaseName()); info.append(", baseData is "); char buffer[10]; sprintf_s(buffer,"%d",b.getBaseData());//VS2012用sprintf报错 info.append(buffer); }
调用show(s,d);编译器报错:
第二点对各种形式的继承作出验证,首先给出表格
继承方式/基类成员类型 | public | protected | private |
public | public | protected | 无法继承 |
protected | protected | protected | 无法继承 |
private | private | private | 无法继承 |
这里解释一下,这里仅仅表达基类的成员,被public,protected,private三种方式继承后,在原基类为public,protectedc,private的成员在继承类里类型为表格里内容
注意两点:
1.对于基类的protected成员,只有在派生类中才可以通过派生类对象访问基类的protected成员。这里说的是在派生类,不是说派生类对象。也就是说只能在派生类的内部访问,不能用派生类对象去访问基类的protected成员。
2.表格中的private成员,基类的private成员可以被子类继承下来,只是派生类不能访问。有人会说这样继承下来是不是没有意义呢,还浪费内存空间。不是,虽然不能直接访问,但是如果基类如果提供了接口,就可以通过这个接口来访问了。
#include<iostream> #include<string> class base { public: std::string testPublic() { return std::string("this is public base"); } protected: std::string testProtected() { return std::string("this is protected base"); } private: std::string testPrivate() { return std::string("this is private base"); } }; class derivedPublic:public base { public: std::string testPubPublic() { return testPublic()+= "in derived"; } std::string testProPublic() { return testProtected()+= "in derived"; } std::string testPriPublic() { return testPrivate()+= "in derived"; } }; int main(int argc,char* argv[]) { derivedPublic dpub; std::cout << dpub.testPublic() << std::endl; }
报错:
另外,对于派生类的派生类而言,也能在类中访问基类的protected成员,它的对象就不能,跟派生类一样。
#include <iostream> #include <string> class base { public: std::string testPublic() { return std::string("this is public base"); } protected: std::string testProtected() { return std::string("this is protected base"); } private: std::string testPrivate() { return std::string("this is private base"); } }; class derivedPublic:public base { public: std::string testPubPublic() { return testPublic()+= "in derived"; } std::string testProPublic() { return testProtected()+= "in derived"; } // std::string testPriPublic() // { // return testPrivate()+= "in derived"; // } }; class deepDerived:public derivedPublic { public: std::string deepProtected() { return testProtected() +="in deep"; } std::string deepPublic() { return testPublic() +="indeep"; } }; int main(int argc,char* argv[]) { derivedPublic dpub; std::cout << dpub.testProtected() << std::endl; deepDerived deepdpub; std::cout<<deepdpub.testPublic() <<std::endl; std::cout<<deepdpub.testProtected() <<std::endl; std::cout<<deepdpub.deepProtected() <<std::endl; std::cout<<deepdpub.deepPublic() <<std::endl; }
报错: