c++ - 访问父类(super class)类型成员对象的 protected 成员——一个优雅的解决方案

标签 c++ design-patterns inheritance

首先,我知道我做不到,我认为这不是重复的问题(thisthis 问题处理的是同一个问题,但他们只想解释为什么它不起作用) .

所以,我对类和继承有类似的概念,我会以某种方式优雅地做一些被禁止的事情。这是一个非常简单的代码片段,它反射(reflect)了我想要做的事情:

#include <iostream>

class A{
protected:
    int var;
    std::vector <double> heavyVar;
public:
    A() {var=1;}
    virtual ~A() {}
    virtual void func() {
        std::cout << "Default behavior" << this->var << std::endl;
    }

    // somewhere along the way, heavyVar is filled with a lot of stuff
};

class B: public A{
protected:
    A* myA;
public:
    B(A &a) : A() {
        this->myA = &a;
        this->var = this->myA->var;
             // copy some simple data, e.g. flags
             // but don't copy a heavy vector variable
    }
    virtual ~B() {}
    virtual void func() {
        this->myA->func();
        std::cout << "This class is a decorator interface only" << std::endl;
    }
};

class C: public B{
private:
    int lotsOfCalc(const std::vector <double> &hv){
        // do some calculations with the vector contents
    }
public:
    C(A &a) : B(a) {
        // the actual decorator
    }
    virtual ~C() {}
    virtual void func() {
        B::func(); // base functionality
        int heavyCalc = lotsOfCalc(this->myA->heavyVar); // illegal
            // here, I actually access a heavy object (not int), and thus
            // would not like to copy it
        std::cout << "Expanded functionality " << heavyCalc << std::endl;
    }
};

int main(void){
    A a;
    B b(a);
    C c(a);
    a.func();
    b.func();
    c.func();
    return 0;
}

这样做的原因是我实际上是在尝试实现 Decorator Pattern (class B 有我要修饰的 myA 内部变量),但我也想使用 class A 的一些 protected 成员> 在进行“装饰”计算时(在 B 类 及其所有子类中)。因此,这个例子不是一个合适的装饰器例子(甚至不是一个简单的例子)。在示例中,我只专注于演示有问题的功能(我想使用但不能使用的功能)。在这个例子中甚至没有使用实现装饰器模式所需的所有类/接口(interface)(我没有抽象基类接口(interface),由具体基类实例继承以及一个抽象装饰器接口(interface),用作具体装饰器的父类(super class))。我只提到上下文装饰器(我想要一个 A* 指针的原因)。

在这种特殊情况下,我认为将(我的等价物)int var 公开(或者甚至编写可公开访问的 getter)有两个原因:

  • 更明显的是,我希望用户直接实际使用信息(我有一些函数返回相关信息和/或写入我的protected 变量,但不是变量值本身)
  • 在我的例子中,protected 变量比 int 更难复制(它是 的二维 std::vector >doubles),并将其复制到派生类的实例中会不必要地耗费时间和内存

现在,我有两种不同的方法让我的代码做我想做的事,但我都不喜欢它们,我正在寻找一个 C++ 概念实际上是为了做这种事情(我不是第一个想要这种行为的人)。

我目前拥有的以及为什么我不喜欢它:

<强>1。向基类声明所有(相关的)继承类 friend:

class A{
    ....
    friend class B;
    friend class C;
};

我不喜欢这个解决方案,因为它会迫使我每次编写新的子类时都修改我的基类,而这正是我的我试图避免。 (我只想在系统的主要模块中使用'A'接口(interface)。)

<强>2。将 A* 指针转换为继承类的指针并使用它

void B::func(){
    B *uglyHack = static_cast<B*>(myA);
    std::cout << uglyHack->var + 1 << std::endl;
}

变量名称非常暗示我使用这种方法的感受,但这是我现在正在使用的方法。由于我设计了这些类,所以我知道如何小心谨慎,只使用在 class A 中实际实现的内容,同时将其视为 class B。但是,如果其他人继续我的项目的工作,他可能对代码不太熟悉。此外,将变量指针转换到我非常清楚它不是的东西对我来说感觉纯粹是邪恶的。

我正在努力让这个项目的代码尽可能的漂亮和干净,所以如果有人对不需要不时修改基类或使用邪恶概念的解决方案有任何建议,我将不胜感激。

最佳答案

我确实相信您可能想重新考虑设计,但是我如何访问成员(member)? 的具体问题的解决方案可能是:

class A{
protected:
    int var;

    static int& varAccessor( A& a ) {
       return a.var;
    }
};

然后在派生类型中调用 protected 访问器,通过引用传递成员对象:

varAccessor( this->myA ) = 5;

现在,如果您正在考虑装饰器模式,我认为这不是可行的方法。 混淆的根源是大多数人没有意识到一个类型有两个独立的接口(interface),面向用户的 public 接口(interface)和用于实现提供者的 virtual 接口(interface)(即派生的类型),因为在许多情况下,函数既是public 又是virtual(即语言允许绑定(bind)两个语义不同的接口(interface))。在装饰器模式中,您使用基本接口(interface)来提供实现。继承是为了使派生类型可以提供通过一些实际工作(装饰)为用户操作,然后将工作转发给实际对象。继承关系不是让你通过 protected 元素以任何方式访问实现对象,这本身就是危险的。如果向您传递了一个派生类型的对象,该对象对 protected 成员具有更严格的不变性(即对于类型 X 的对象,var 必须是奇数),您采用的方法会让 < em>装饰器(某种程度上)打破了应该被装饰的 X 类型的不变量。

关于c++ - 访问父类(super class)类型成员对象的 protected 成员——一个优雅的解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9946135/

相关文章:

c++ - 将 vector 传递给cpp中的多个文件

java - 中介模式在这种情况下有效吗?

design-patterns - 微服务中需要事务发件箱模式

javascript - 将状态从控件发送到框​​架

c++ - 将 NumPy 切片循环转换为 C++

c++ - 使用 WINAPI ReadFile 从文件异步读取行

c++ - 将 list 嵌入到 exe 文件

c# - 私有(private)静态变量和实例变量是否在 C# 中继承,为什么?

带有 IUnityContainer 的 WPF MVVM 创建不需要的多个实例

c# - 只允许为特定类实现接口(interface)