【问题标题】:Accessibility of C++ vector in derived class from base class从基类派生类中 C++ 向量的可访问性
【发布时间】:2014-03-07 09:34:17
【问题描述】:

我的场景在下面的例子中得到了简化:

#include <iostream>
#include <vector>
using namespace std;
class C;
class A
{
  protected:
    C * cPointer;
    A();
    virtual void updateList() = 0;
    void callFunc();
};

class B : public A
{
  private:
    vector<int> list;
    void updateList();
  public:
    void callFromA();
};

class C
{
  friend class A;
  friend class B; // I want to get rid off this declaration
  private:
    int sum;
    void set_sum( int val );
  public:
    static C * getCPointer();
};

A::A()
{
  cPointer = C::getCPointer();
}

void A::callFunc()
{
  updateList();
}

void B::updateList()
{
  list.push_back(2);
  list.push_back(4); 
  int s = 0;
  for( unsigned int i=0; i<list.size(); i++ )
  {
    s += list[i];
  }
  cPointer->set_sum(s);
}

void B::callFromA()
{
  callFunc();
}

void C::set_sum( int val )
{
  sum = val;
  cout << "Sum at C is: " << sum << endl;
}

C * C::getCPointer()
{
  static C cPointer;
  return & cPointer;
}

int main( int argc, char ** argv)
{
  B b;
  b.callFromA();
  return 0;
}

这个例子运行良好。但我想摆脱 C 类中的“朋友 B 类”声明并实现类似的功能。其实我想要以下任何一种:

  1. C::set_sum() 从 B::updateList() 的可访问性,如果没有 C 类中的“朋友类 B”声明,这是不可能的。

  2. A::callFunc() 中 B::list 的可访问性,我可以将逻辑从 B::updateList 推送到 A::callFunc(),这基本上意味着能够访问派生类中的列表基类。这样,由于 C 类中的“friend class A”声明,我将能够访问 A::callFunc() 中的 set_sum()。

在不涉及重大设计更改的情况下实现这一点的任何想法都是可取的!

谢谢!

【问题讨论】:

  • 你是从B::callFromA()调用全局函数callFunc()吗?那么它在哪里呢?
  • 这里的问题可能是您将拥有许多来自基类A 的派生类,并且您不想将所有这些类都列为C 的朋友。为了帮助实现这一点,您可以只将基类A 设为C 的朋友,并且可以将受保护的set_sum() 方法放入A 中,所有派生类都可以调用该方法,所有这些A::set_sum 都可以正在将呼叫转接到C::set_sum。这个转发函数调用将被编译器优化掉。
  • @barakmanos: callFunc() 作用于 A 并从 B::callFromA() 调用,因为 B 派生自 A。
  • @Code Warrior:是的,我现在明白了;谢谢。
  • @pasztorpisti:这看起来是一个简单而有效的解决方案..谢谢!

标签: c++ inheritance friend derived-class


【解决方案1】:

我不确定我是否了解您的所有限制,但也许这对您更有效。基本上,您可以使用虚函数从A 访问B::list。我已经注释了代码中的更改。

#include <iostream>
#include <vector>
using namespace std;
class A;

class C
{
    friend class A;
private:
    int sum;
    void set_sum(int val);
public:
    static C * getCPointer();
};

class A
{
protected:
    C * cPointer;
    A();
    virtual int getS() = 0;             // virtual function to calculate data from vector in derived class B
    virtual void updateList()
    {
        cPointer->set_sum(getS());      // A is friend of C, so you can access B data from A
    }
    void callFunc();
};

class B : public A
{
private:
    vector<int> list;
    void updateList();

    int getS()                          // concrete implementation to access vector data
    {
        int s = 0;
        for (unsigned int i = 0; i < list.size(); i++)
        {
            s += list[i];
        }
        return s;
    }


public:
    void callFromA();
};

A::A()
{
    cPointer = C::getCPointer();
}

void A::callFunc()
{
    updateList();
}

void B::updateList()
{
    list.push_back(2);
    list.push_back(4);
    A::updateList();                    // Call to super implementation
}

void B::callFromA()
{
    callFunc();
}

void C::set_sum(int val)
{
    sum = val;
    cout << "Sum at C is: " << sum << endl;
}

C * C::getCPointer()
{
    static C cPointer;
    return &cPointer;
}

int main(int argc, char ** argv)
{
    B b;
    b.callFromA();
    return 0;
}

【讨论】:

  • 感谢您的评论..我不允许将其设为公共功能,因为这是内部功能,不应暴露给用户..但是,我们只能在其中添加一些新内容受保护/私有范围!
【解决方案2】:

您不能在基类中访问派生类的成员,句号。手头的对象可能是基类,甚至是完全不相关的派生类,保证“有趣”的连续性。任何要求这样做的设计都被严重破坏,需要重新考虑。

您可以将想要这样做的基类的成员函数设为虚拟,并在派生类中重新定义它以执行您想要的任何变态。同时,基类的纯洁成员可以拒绝被调用,以理智的方式发出错误信号。这样您就可以保证不会发生任何不愉快的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-21
    • 2011-12-07
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 2015-02-23
    相关资源
    最近更新 更多