从基类派生类中 C++ 向量的可访问性

Posted

技术标签:

【中文标题】从基类派生类中 C++ 向量的可访问性【英文标题】:Accessibility of C++ vector in derived class from base class 【发布时间】: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 类”声明并实现类似的功能。其实我想要以下任何一种:

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

    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:这看起来是一个简单而有效的解决方案..谢谢! 【参考方案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】:

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

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

【讨论】:

以上是关于从基类派生类中 C++ 向量的可访问性的主要内容,如果未能解决你的问题,请参考以下文章

从基类类型的向量访问派生类方法

如何使用多态性从基类访问派生类向量成员?

如何从基类 C++ 访问派生数据

从基类c ++的向量中的派生类调用虚拟方法[重复]

继承与派生

C ++跨类访问基对象向量中的派生对象的引用