【问题标题】:C++11 seems impossible to access a protected member through a shared_ptr [duplicate]C ++ 11似乎不可能通过shared_ptr访问受保护的成员[重复]
【发布时间】:2016-02-04 00:03:48
【问题描述】:

似乎无法通过 shared_ptr 访问受保护的成员。这是一个无法编译的最小示例:

// compile with g++ -std=c++11 protect.cpp

#include <iostream>
#include <memory>

class C
{
   public:
      C(int xval = 0) : x(xval) {}

   protected:
      int x = 0;
};

class D : public C
{
   public:
      D(int xval = 0) : C(xval) {}
      void print_sum( const std::shared_ptr<C>& other );
};

void D::print_sum( const std::shared_ptr<C>& other )
{
   int sum = x + other->x;
   std::cout << "the sum is " << sum << std::endl;
}

int main( int argc, char** argv, char** envp)
{
   std::shared_ptr<C> first = std::make_shared<C>(2);
   std::shared_ptr<D> second = std::make_shared<D>(3);

   second->print_sum( first );
   return 0;
}

以下是我收到的具体错误消息:

$ g++ -std=c++11 protect.cpp
protect.cpp: In member function ‘void D::print_sum(const std::shared_ptr<C>&)’:
protect.cpp:13:15: error: ‘int C::x’ is protected
       int x = 0;
               ^
protect.cpp:25:25: error: within this context
    int sum = x + other->x;

虽然D 派生自C,但D 无权访问x 似乎很奇怪,而且我一直认为派生类可以使用protected 基类成员。

这个问题对我来说并不是一个真正的障碍;在我的用例中,CD 将作为同一补丁集的一部分实现,因此将x 公开作为一种解决方法很容易。但是有没有更“惯用”的方式来使这段代码工作?

以防万一这是 gcc 错误,以下是我正在使用的版本:

$ cat /etc/issue
Ubuntu 14.04.3 LTS \n \l

$ g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

【问题讨论】:

  • 给朋友打电话(眨眼眨眼)
  • 这有nothing to doshared_ptrD 只能通过 D 实例访问继承的受保护成员。
  • 直到去年左右,我的大部分 OO 编程一直在使用 Java...我只是假设 protected 在 C++ 中的含义与在 Java 中的含义相似,但显然在 C++ 中它意味着“允许访问所有父类”,而在 Java 中它的意思是“允许访问所有派生类”。我还用 Python 进行了大量编程,这导致我自然倾向于放弃访问说明符并将所有内容公开,这种经历似乎强化了...

标签: c++ oop c++11 inheritance shared-ptr


【解决方案1】:

引用此SO answer

您只能在您的类型的实例中访问受保护的成员(或 派生自您的类型)。您不能访问受保护的成员 父类或表亲类的实例。

这意味着您只能从 D 访问 this-&gt;xd.x(其中 dD 类型的另一个对象),而不是 c.x 即使 c 是 @987654328 类型的对象@。

解决方法是将 D 声明为 C 的朋友:

class D; // forward declare D
class C
{
   public:
      C(int xval = 0) : x(xval) {}

      friend class D; // <--
   protected:
      int x = 0;

};

或者获取参数为C,而不是D:

// no need for any friend declaration for this
void print_sum( const std::shared_ptr<D>& other ); 

顺便说一句,这与共享指针无关。

【讨论】:

    猜你喜欢
    • 2010-12-22
    • 2017-10-15
    • 2021-01-09
    • 1970-01-01
    • 2016-04-14
    • 1970-01-01
    • 2012-05-26
    • 2013-08-06
    • 2016-01-07
    相关资源
    最近更新 更多