测试问题
派生类默认情况下是以什么控制权限继承基类的?
我们知道,像如下代码中的派生类继承基类,访问权限都是明确的:
// 公有继承
class Pub_quote : public Quote {/.../}
// 私有继承
class Pri_quote : private Quote {/.../}
// 保护继承
class Pro_quote : protected Quote {/.../}
而在没有明确访问权限的情况下,派生类是怎么继承基类的?
测试过程
为了弄清楚这个问题,我用VS2017按照如下步骤进行了访问测试:
1、定义简单的基类Base,以及派生类Dir_base:Base和Dir_db:Dir_base。
2、用派生类的公共成员函数调用基类的公共成员,检验是否允许调用。
3、改变两个派生类的类派生列表中的访问控制,观察9种访问控制组合中,哪些与默认情况相同。
代码如下(头文件iostream,string):
定义基类Base
class Base
{
public:
Base() = default;
Base(const std::string& s, int i) : pri_str(s), pro_num(i) {}
int pub_num; //基类的公共成员,可以被派生类访问
private:
std::string pri_str;
protected:
int pro_num;
};
定义派生类Dir_base:Base及其成员函数
class Dir_base : Base
{
public:
Dir_base() = default;
Dir_base(const std::string& s,int i, std::size_t n ): Base(s,i) , sn(n) {}
void function1(const std::string& s, int i, std::size_t n);
private:
std::size_t sn;
};
void Dir_base::function1(const std::string& s, int i, std::size_t n)
{
Dir_base db(s, i, n);
Dir_base* db_ptr = &db;
std::cout << db_ptr->pub_num << std::endl; //无论什么继承都可以访问pub_num
}
定义派生类Dir_db:Dir_base及其成员函数
class Dir_db : Dir_base
{
public:
Dir_db() = default;
Dir_db(const std::string& s, int i, std::size_t n) :Dir_base(s, i, n) {}
void function2(const std::string& s, int i, std::size_t n);
};
void Dir_db::function2(const std::string& s, int i, std::size_t n)
{
Dir_db ddb(s, i, n);
Dir_db* ddb_ptr = &ddb;
std::cout << ddb_ptr->pub_num << std::endl; //只有public和protected继承才能访问pub_num,否则报错
}
此时,VS会在function2的ddb_ptr->pub_num处提示:
测试结论
默认情况下派生类private继承基类。
结论分析
我们知道,基类成员的访问权限,在不同继承权限的派生类中的变化情况如下表:
基类 | public继承 | protected继承 | private继承 |
---|---|---|---|
public成员 | public | protected | 不可访问 |
protected成员 | protected | protected | 不可访问 |
private成员 | private | private | 不可访问 |
更改上述代码的类派生列表中修饰基类的访问控制,可以得到 :
1、默认情况下
派生类Dir_base的function1可以调用Base的pub_num,Dir_db的function2不可以调用Base的pub_num。
2、Dir_base 私有继承Base的情况下
派生类Dir_db无论怎么样继承Dir_base都不能调用Base的pub_num。
3、Dir_base 非私有继承Base的其他情况
派生类Dir_db可以调用Base的pub_num。
原因:
这是因为当Dir_base类采用public和protected继承Base的时候,Base的公共成员pub_num在该类中的访问权限分别是public和protected,此时Dir_base的派生类Dir_db仍然可以访问pub_num。
而当Dir_base类采用private继承的时候,Base的所有成员在该类中的访问权限变成“不可访问”,即除了该类的成员函数可以调用其他成员变量以外,其派生类和其他类都不能访问该类的成员。