c++中公共继承、私有继承和受保护继承之间的区别是什么?
我在SO上找到的所有问题都是针对具体案例的。
c++中公共继承、私有继承和受保护继承之间的区别是什么?
我在SO上找到的所有问题都是针对具体案例的。
当前回答
它本质上是派生类中基类的公共和受保护成员的访问保护。通过公共继承,派生类可以看到基类的公共成员和受保护成员。而私有继承则不能。使用protected,派生类及其派生的任何类都可以看到它们。
其他回答
私人:
基类的私有成员只能被该基类的成员访问。
公众:
基类的公共成员可以被该基类的成员、其派生类的成员以及基类和派生类之外的成员访问。
保护:
基类的成员可以访问基类的受保护成员,也可以访问其派生类的成员。
简而言之:
私人:基地
Protected:基础+派生
Public: base + derived +任何其他成员
这三个关键字还在完全不同的上下文中用于指定可见性继承模型。
这个表收集了组件声明和继承模型的所有可能组合,表示在子类完全定义后对组件的最终访问。
上表的解释如下(看第一行):
如果一个组件被声明为公共的,并且它的类被继承为公共的,那么得到的访问是公共的。
一个例子:
class Super {
public: int p;
private: int q;
protected: int r;
};
class Sub : private Super {};
class Subsub : public Sub {};
Subsub类中变量p, q, r的访问结果为none。
另一个例子:
class Super {
private: int x;
protected: int y;
public: int z;
};
class Sub : protected Super {};
类Sub中对变量y, z的访问受到保护,对变量x的访问为none。
一个更详细的例子:
class Super {
private:
int storage;
public:
void put(int val) { storage = val; }
int get(void) { return storage; }
};
int main(void) {
Super object;
object.put(100);
object.put(object.get());
cout << object.get() << endl;
return 0;
}
现在让我们定义一个子类:
class Sub : Super { };
int main(void) {
Sub object;
object.put(100);
object.put(object.get());
cout << object.get() << endl;
return 0;
}
定义了一个名为Sub的类,它是一个名为Super的类的子类,或者这个子类是从Super类派生的。 子类既不引入新变量也不引入新函数。这是否意味着子类的任何对象都继承了父类之后的所有特征,实际上是父类对象的副本?
不。它不是。
如果我们编译下面的代码,我们只会得到编译错误,表示put和get方法不可访问。为什么?
当省略可见性说明符时,编译器假定我们将应用所谓的私有继承。这意味着所有的公共超类组件都变成了私有访问,私有超类组件将根本无法访问。因此,这意味着不允许在子类中使用后者。
我们必须通知编译器我们想要保留以前使用的访问策略。
class Sub : public Super { };
不要被误导:这并不意味着私人组件的超 类(如存储变量)将转换为公共类 有点神奇。私有组件将保持私有、公开 将继续公开。
子类的对象可以做“几乎”与从超类创建的它们的哥哥姐姐相同的事情。“几乎”是因为作为子类的事实也意味着该类失去了对超类的私有组件的访问权。子类的成员函数不能直接操作存储变量。
这是一个非常严重的限制。有什么解决办法吗?
Yes.
第三个访问级别称为受保护。关键字protected意味着标记了它的组件在被任何子类使用时表现得像一个公共组件,而对其他组件看起来像一个私有组件。——这只适用于公共继承的类(比如我们例子中的Super类)——
class Super {
protected:
int storage;
public:
void put(int val) { storage = val; }
int get(void) { return storage; }
};
class Sub : public Super {
public:
void print(void) {cout << "storage = " << storage;}
};
int main(void) {
Sub object;
object.put(100);
object.put(object.get() + 1);
object.print();
return 0;
}
正如你在示例代码中看到的,我们给子类添加了一个新功能,它做了一件重要的事情:它从超类访问存储变量。
如果变量被声明为私有,这是不可能的。 在main函数的作用域中,变量仍然是隐藏的,所以如果你这样写:
object.storage = 0;
编译器会告诉你这是一个错误:'int Super::storage'是受保护的。
最后,最后一个程序将产生以下输出:
storage = 101
它本质上是派生类中基类的公共和受保护成员的访问保护。通过公共继承,派生类可以看到基类的公共成员和受保护成员。而私有继承则不能。使用protected,派生类及其派生的任何类都可以看到它们。
Member in base class : Private Protected Public
继承类型:对象继承为:
Private : Inaccessible Private Private
Protected : Inaccessible Protected Protected
Public : Inaccessible Protected Public
我发现了一个简单的答案,所以我想把它贴出来,作为我未来的参考。
它来自http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/的链接
class Base
{
public:
int m_nPublic; // can be accessed by anybody
private:
int m_nPrivate; // can only be accessed by Base member functions (but not derived classes)
protected:
int m_nProtected; // can be accessed by Base member functions, or derived classes.
};
class Derived: public Base
{
public:
Derived()
{
// Derived's access to Base members is not influenced by the type of inheritance used,
// so the following is always true:
m_nPublic = 1; // allowed: can access public base members from derived class
m_nPrivate = 2; // not allowed: can not access private base members from derived class
m_nProtected = 3; // allowed: can access protected base members from derived class
}
};
int main()
{
Base cBase;
cBase.m_nPublic = 1; // allowed: can access public members from outside class
cBase.m_nPrivate = 2; // not allowed: can not access private members from outside class
cBase.m_nProtected = 3; // not allowed: can not access protected members from outside class
}