访问超类类型成员对象的受保护成员 - 优雅的解决方案 [英] Accessing a protected member of a superclass-typed member object - an elegant solution

查看:82
本文介绍了访问超类类型成员对象的受保护成员 - 优雅的解决方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我知道我不能这样做,我认为这不是一个重复的问题(问题处理相同的问题,但他们只需要解释为什么它不工作)。

First off, I know I can not do it, and I think it's not a duplicate questions (this and this questions deal with the same problem, but they only want an explanation of why it does not work).

所以,我有一个类和继承的概念,我会,不知何故,优雅,想做一些事情禁止。这里有一个非常简单的代码片段,它反映了我要做的事情:

So, I have a similar concept of classes and inheritance and I would, somehow, elegantly, want to do something that's forbidden. Here's a very simple code snippet that reflects what I want to do:

#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;
}

这样做的原因是我实际上试图实现< a href =http://en.wikipedia.org/wiki/Decorator_pattern =nofollow>装饰模式( B类 myA 我想装饰的内部变量),但我也想使用 class A 的一些受保护的成员做装饰计算(在类B 和它的所有子类)。因此,此示例不是装饰器的正确示例(甚至不是简单的)。在示例中,我只专注于演示有问题的功能(我想使用,但我不能)。在这个例子中,甚至不需要实现Decorator模式所需的所有类/接口(我没有由具体的基类实例继承的抽象基类接口以及用作具体装饰器的超类)的抽象装饰器。我只提到装饰器的上下文(我想要一个 A * 指针的原因)。

The reason for doing this is that I'm actually trying to implement a Decorator Pattern (class B has the myA inner variable that I want to decorate), but I would also like to use some of the protected members of class A while doing the "decorated" calculations (in class B and all of it's subclasses). Hence, this example is not a proper example of a decorator (not even a simple one). In the example, I only focused on demonstrating the problematic functionality (what I want to use but I can't). Not even all the classes/interfaces needed to implement a Decorator pattern are used in this example (I don't have an abstract base class interface, inherited by concrete base class instances as well as an abstract decorator intreface, to be used as a superclass for concrete decorators). I only mention Decorators for the context (the reason I want a A* pointer).

,我没有看到很多有意义的(我的等价) int var public(甚至,写一个公共可访问的getter)有两个原因:

In this particular case, I don't see much sense in making (my equivalent of) int var public (or even, writing a publicly accessible getter) for two reasons:


  • 更明显的一个,我不要希望用户直接使用信息(我有一些函数返回信息相关和/或写入我的 protected 变量,而不是变量值本身)

  • protected int (这是一个2D std :: vector of double s),并将其复制到派生类的实例将不必要地耗费时间和内存。

  • the more obvious one, I do not want the users to actually use the information directly (I have some functions that return the information relevant to and/or written in my protected variables, but not the variable value itself)
  • the protected variable in my case is much more heavy to copy than an int (it's a 2D std::vector of doubles), and copying it in to the instance of a derived class would be unnecessarily time- and memory-consuming

现在,我有两种不同的方式让我的代码做我想做的,但我不喜欢他们,我正在搜索对于一个 C ++ 概念,实际上是用于做这样的事情(我不能是第一个人想要这种行为)。

Right now, I have two different ways of making my code do what I want it to do, but I don't like neither of them, and I'm searching for a C++ concept that was actually intended for doing something of this sort (I can't be the first person to desire this behavior).

到目前为止,我为什么不喜欢它:

What I have so far and why I don't like it:

1。向基类声明所有(相关)继承类 friend s:

1. declaring all the (relevant) inherited classes friends to the base class:

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

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

I don't like this solution because it would force me to modify my base class every time I write a new subclass class, and this is exactly what I'm trying to avoid. (I want to use only the 'A' interface in the main modules of the system.)

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

2. casting the A* pointer into a pointer of the inherited class and working with that

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

变量名称对我使用这种方法的感觉非常暗示,是我现在使用的。因为我设计了这个类,我知道如何小心,只使用在 class A 中实现的东西,同时将它作为类B 。但是,如果有人继续我的项目的工作,他可能不是那么熟悉的代码。此外,将一个变量指针投射到我非常清楚地知道它不是只是对我感觉纯粹的邪恶。

The variable name is pretty suggestive towards my feelings of using this approach, but this is the one I am using right now. Since I designed this classes, I know how to be careful and to use only the stuff that is actually implemented in class A while treating it as a class B. But, if somebody else continues the work on my project, he might not be so familiar with the code. Also, casting a variable pointer in to something that I am very well aware that it is not just feels pure evil to me.

我是试图保持这个项目的代码尽可能好的和干净的设计,所以如果任何人有一个解决方案,不需要修改一个基类每时每刻或使用邪恶的概念,我会非常感谢。

I am trying to keep this projects' code as nice and cleanly designed as possible, so if anybody has any suggestions towards a solution that does not require the modification of a base class every now and then or usage of evil concepts, I would very much appreciate it.

推荐答案

我想我在继承结构中找到了一个 nice

I think I found a nice way to do what I want in the inheritance structure I have.

首先,在 base 类(一个是所有其他类的基础,在Decorator Pattern中的基类接口),我为第一个子类添加 friend类声明作为抽象装饰器接口):

Firstly, in the base class (the one that is a base for all the other classes, as well as abstract base class interface in the Decorator Pattern), I add a friend class declaration only for the first subclass (the one that would be acting as abstract decorator interface):

class A{

    ....
    friend class B;
};

然后,我添加 protected 基类中所有有趣变量的子类:

Then, I add protected access functions in the subclass for all the interesting variables in the base class:

class B : public A{

    ...
    protected:
        A *myA;
        int getAVar() {return myA->var;}
        std::vector <double> &getAHeavyVar {return myA->heavyVar;}
};

最后,我可以访问所有继承 c> static_cast > > > > )通过访问函数而不需要来创建 friend 的<的所有子类$ c> A类

And finally, I can access just the things I need from all the classes that inherit class B (the ones that would be concrete decorators) in a controlled manner (as opposed to static_cast<>) through the access function without the need to make all the subclasses of B friends of class A:

class C : public B{

    ....
    public:
        virtual void func() {
        B::func(); // base functionality
        int heavyCalc = lotsOfCalc(this->getAHeavyVar); // legal now!
            // here, I actually access a heavy object (not int), and thus
            // would not like to copy it
        std::cout << "Expanded functionality " << heavyCalc << std::endl;
        std::cout << "And also the int: " << this->getAVar << std::endl;
            // this time, completely legal
    }
};

我也试图只给出 class B 一个朋友访问(声明他们作为朋友函数),但是没有工作,因为我需要声明类B A类中的朋友声明之前。因为在这种情况下,类B 继承类A ,这将给我循环依赖 c> c>仅仅使用友元函数是不够的,但对于一个好友类声明来说,它的工作正常。)

I was also trying to give only certain functions in the class B a friend access (declaring them as friend functions) but that did not work since I would need to declare the functions inside of class B before the friend declaration in class A. Since in this case class B inherits class A, that would give me circular dependency (forward declaration of class B is not enough for using only friend functions, but it works fine for a friend class declaration).

这篇关于访问超类类型成员对象的受保护成员 - 优雅的解决方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆