私有成员和受保护成员:C ++


276

有人可以启发我关于privateprotected班级成员之间的区别吗?

我从最佳实践惯例中了解到,应该制作在类之外没有调用的变量和函数private-但是在我的MFC项目中,MFC似乎更受欢迎protected

有什么区别,我应该使用哪个?

Answers:


374

私有成员只能在定义它们的类中访问。

受保护的成员可以在定义它们的类以及从该类继承的类中访问。

编辑:他们的班级的朋友也可以访问它们,对于受保护的成员,他们派生的班级的朋友也可以访问它们。

编辑2:根据您的问题使用任何有意义的方法。您应该尽可能地使成员成为私有成员,以减少耦合并保护基类的实现,但是,如果那不可能,则使用受保护的成员。查看C ++常见问题解答,以更好地了解该问题。有关受保护变量的问题也可能会有所帮助。


12
C ++ FAQ Lite的链接已移至isocpp.org/wiki/faq/basics-of-heritance
avner 2015年

134

每个人都可以访问A类的公共成员。

类A的受保护成员不能从A的代码之外访问,但是可以从从A派生的任何类的代码访问。

在A的代码之外或从A派生的任何类的代码之外,无法访问A类的私有成员。

因此,最后,在受保护的或私有的之间进行选择将回答以下问题:您愿意对派生类的程序员信任多少?

默认情况下,假设派生类不受信任,并将您的成员设为private。如果您有充分的理由让母类的内部对象可以自由访问其派生类,则可以使它们受到保护。


派生类应该是您的类的一种,基类的受保护数据是派生类的数据的一部分。派生类的编写者应正确处理此数据,否则可能是错误。但是,基类中的私有数据是派生类的编写者无法控制的。
CashCow

@CashCow the protected data of the base class is part of the data of the derived class.确实。那么,让派生类的编写者在其类中声明数据而不是我的数据不是更好吗?... :-) ... The writer of the derived class is expected to handle this data properly or it is a bug.在NVI模式中,目标是使所有内容私有,包括方法,以限制派生类编写者可能对层次结构造成的损害。受保护的方法已经是一个潜在的问题。我不认为通过使用保护状态来加剧这种情况是正确的方法。
paercebal '16

可能是这样,这将要求您在基类中具有虚拟“获取器”才能访问它。而且,尽管您可以使用中间类来执行数据模式的不同实现方式,但这并不总是可行的。例如,在C ++中多数时候没有必要,但在没有“ const”修饰符的语言中常见的“模式”是具有只读基类和可写派生类。在C ++中,这也可能很好,因为您想要一种以上的方式来加载(初始化)数据。
CashCow

有多种方法可以做到这一点。让您的序列化课程成为朋友。将所有数据放入具有公共访问权限的结构中,但是您的类具有此变量的私有成员....受保护的成员和派生类可以从任何来源加载,有时更容易。
CashCow

63

可以从派生类访问受保护的成员。私人的不能。

class Base {

private: 
  int MyPrivateInt;
protected: 
  int MyProtectedInt;
public:
  int MyPublicInt;
};

class Derived : Base
{
public:
  int foo1()  { return MyPrivateInt;} // Won't compile!
  int foo2()  { return MyProtectedInt;} // OK  
  int foo3()  { return MyPublicInt;} // OK
};‌‌

class Unrelated 
{
private:
  Base B;
public:
  int foo1()  { return B.MyPrivateInt;} // Won't compile!
  int foo2()  { return B.MyProtectedInt;} // Won't compile
  int foo3()  { return B.MyPublicInt;} // OK
};

在“最佳实践”方面,这取决于。如果某人甚至很可能想要从您现有的班级派生一个新班级并需要访问内部成员,请将其设置为受保护的,而不是私有的。如果它们是私有的,则您的类可能很难从中轻松继承。


3
我谨作不同的解释:如果很可能没有子类需要它,请将其设为私有。除非打算将您的类设为子类,否则请使用模板方法模式。
xtofl

23

MFC偏爱受保护的原因是因为它是一个框架。您可能想对MFC类进行子类化,在这种情况下,需要一个受保护的接口来访问对该类的常规使用不可见的方法。


9

这完全取决于您要执行的操作以及希望派生类能够看到的内容。

class A
{
private:
    int _privInt = 0;
    int privFunc(){return 0;}
    virtual int privVirtFunc(){return 0;}
protected:
    int _protInt = 0;
    int protFunc(){return 0;}
public:
    int _publInt = 0;
    int publFunc()
    {
         return privVirtFunc();
    }
};

class B : public A
{
private:
    virtual int privVirtFunc(){return 1;}
public:
    void func()
    {
        _privInt = 1; // wont work
        _protInt = 1; // will work
        _publInt = 1; // will work
        privFunc(); // wont work
        privVirtFunc(); // wont work
        protFunc(); // will work
        publFunc(); // will return 1 since it's overridden in this class
    }
}

6

protected与私有属性不同,标记为的属性和方法仍然在子类中可见。

除非您不想在可能的子类中使用或提供重写该方法的可能性,否则我将其设置为private


2
派生类可以覆盖其基础的私有虚拟函数
詹姆斯霍普金

6

当然,请看一下“ 保护成员变量”问题。建议使用private作为默认值(就像C ++ classses一样)以减少耦合。受保护的成员变量总是一个坏主意,受保护的成员函数可以用于例如模板方法模式。


有趣的是,我在看到您的帖子之前将其编辑到我的帖子中。由于羽毛鸟偶然碰到相同的链接而被
投票


4

私有成员只能从类内部访问,受保护成员可以在类和派生类中访问。这是OO语言中继承的功能。

您可以在C ++中拥有私有,受保护和公共继承,这将确定在继承层次结构中可以访问哪些派生类。例如,C#仅具有公共继承。


3

私人 =只能由母舰(基类)访问(即只有我的父母可以进入父母的卧室)

受保护 =可以由母权(基层)和她的女儿访问(即只有我父母可以进入父母的卧室,但允许儿子/女儿进入父母的卧室)

public =母权(基类),女儿和其他所有人均可访问(即,只有我父母可以进入父母的卧室,但这是家庭聚会-mi casa su casa)


2

由于不需要公共成员函数来获取和更新派生类中的受保护成员,因此这提高了代码效率,并减少了我们需要编写的代码量。但是,派生类的程序员应该知道他在做什么。


您始终可以使用在类声明中实现的内联函数。编译器将对此进行优化(例如,这将是对私有成员变量强制进行只读访问的好方法)。
保罗·桑德斯

2

private是首选的成员数据。private默认情况下,C ++类中的成员是。

public尽管这是一个意见问题,但成员函数还是首选。至少某些方法必须可访问。public所有人都可以使用。这是最灵活,最不安全的选择。任何人都可以使用它们,任何人都可以滥用它们。

private根本无法访问。没有人可以在课堂外使用它们,也没有人可以滥用它们。甚至在派生类中也没有。

protected这是一种折衷,因为它可以在派生类中使用。从类派生时,您对基类有很好的了解,并且请小心不要滥用这些成员。

MFC是Windows API的C ++包装器,它更喜欢publicprotected。由Visual Studio生成的类向导有一个丑陋的组合protectedpublicprivate成员。但是MFC类本身有一些逻辑。

会员如SetWindowTextpublic,因为你经常需要访问这些成员。

成员,如OnLButtonDown,处理窗口收到的通知。不应访问它们,因此可以访问它们protected。您仍然可以在派生类中访问它们以覆盖这些功能。

一些成员必须执行线程和消息循环,不应访问或覆盖它们,因此将它们声明为 private

在C ++结构中,成员public默认为。结构通常仅用于数据,而不用于方法,因此public声明被认为是安全的。


1
您编写“ C ++类中的成员默认情况下受保护”。根据标准,默认情况下它们是私有的还是公共的,具体取决于定义(14p3)中使用了哪个关键字。Microsoft是否偏离此处的标准?
亚历山大·克劳尔

@AlexanderKlauer我错了,private默认情况下在Visual Studio中。这是private在默认情况下GCC为好,它永远不会public被默认。除非我又错了。我找不到您所指的标准。
Barmak Shemirani

抱歉,我应该更具体一些。我指的是C ++ 17标准。C ++ 11标准在11p3中具有相同的措辞。你能更新你的答案吗?谢谢!
亚历山大·克劳尔

1

私有成员只能在已声明的同一类中访问,而受保护成员可以在声明了它的类及其继承的类中访问。


1
  • 私有:这是一个访问说明符。默认情况下,实例(成员)变量或c ++ / java中类的方法是私有的。在继承期间,代码和数据始终被继承,但在类外部无法访问。我们可以将我们的数据成员声明为私有成员,这样就没有人可以直接更改我们的成员变量,并且可以提供公共获取者和设置者来更改我们的私有成员。并且这个概念总是在业务规则中应用。

  • 受保护的:它也是访问说明符。在C ++中,受保护的成员可以在类内部以及继承的类中访问,但不能在类外部访问。在Java中,受保护的成员在类内,继承的类以及同一包内的所有类均可访问。


0

可以使用以下任一方法,从该基类派生的任何类的成员和朋友访问受保护的非静态基类成员:

  • 指向直接或间接派生类的指针
  • 对直接或间接派生类的引用
  • 直接或间接派生类的对象

0

私有:可通过班级成员功能和朋友功能或朋友班级访问。对于C ++类,这是默认的访问说明符。

受保护:可由类成员函数,朋友函数或朋友类及派生类访问。

  • 您可以根据需要将类成员变量或函数(甚至是typedef或内部类)保留为私有或受保护的。
  • 大多数时候,您将类成员保留为私有成员,并添加get / set函数进行封装。这有助于维护代码。
  • 通常,当您要保持公共功能模块化或消除重复的代码而不是将整个代码写入单个功能时,将使用私有功能。这有助于代码的维护。

请参阅此链接以获取更多详细信息。


-2

私有和受保护的访问修饰符是相同的,只是在孩子(派生)类的基类范围之外可以访问基类的受保护成员。它也适用于继承。但是使用private修饰符时,只能在基类及其朋友功能的范围或代码中访问基类的成员''


5
您的答案与其他答案相比有什么价值?
HermannDöppes'16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.