c – 访问超类型成员对象的受保护成员 – 一种优雅的解决方案
首先,我知道我做不到,我认为这不是一个重复的问题(
this和
this问题处理同样的问题,但他们只想解释为什么它不起作用).
所以,我有类和继承的类似概念,我会以某种方式优雅地想要做一些被禁止的事情.这是一个非常简单的代码片段,反映了我想要做的事情: #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(B类有我想要装饰的myA内部变量),但是我还想使用A类的一些受保护成员来做“装饰“计算(在B类及其所有子类中).因此,这个例子不是装饰器的正确例子(甚至不是简单的装饰器).在这个例子中,我只专注于演示有问题的功能(我想要使用但我不能).在这个例子中,甚至没有实现Decorator模式所需的所有类/接口(我没有抽象的基类接口,由具体的基类实例继承,以及抽象装饰器接口,用作超类)用于混凝土装饰器).我只提到装饰器的上下文(我想要一个A *指针的原因). 在这种特殊情况下,我认为制作(相当于)int var public(甚至编写一个可公开访问的getter)有两个原因: >更明显的一个,我不希望用户直接实际使用信息(我有一些函数返回与我的受保护变量相关和/或写入的信息,但不是变量值本身) 现在,我有两种不同的方式让我的代码做我想做的事情,但我不喜欢它们,我正在寻找一个实际上用于做这类事情的C概念(我不能成为第一个渴望这种行为的人). 到目前为止我有什么,为什么我不喜欢它: 1.将所有(相关的)继承类的朋友声明为基类: class A{ .... friend class B; friend class C; }; 我不喜欢这个解决方案,因为每次我编写一个新的子类时它都会强迫我修改我的基类,这正是我想要避免的. (我想在系统的主要模块中只使用’A’接口.) 2.将A *指针转换为继承类的指针并使用它 void B::func(){ B *uglyHack = static_cast<B*>(myA); std::cout << uglyHack->var + 1 << std::endl; } 变量名对我使用这种方法的感觉很有启发性,但这是我现在正在使用的那个.因为我设计了这个类,所以我知道如何小心并且只使用A类中实际实现的东西,同时将它作为B类处理.但是,如果其他人继续我的项目工作,他可能不是这样熟悉代码.另外,将一个变量指针投射到我非常清楚的事情中,这对我来说不仅仅是纯粹的邪恶. 我试图让这些项目的代码尽可能干净整洁,所以如果有人对解决方案有任何建议,不需要时不时地修改基类或使用邪恶的概念,我会非常感谢欣赏它. 解决方法
我相信您可能想重新考虑设计,但是我可以如何访问该成员的具体问题的解决方案?可能:
class A{ protected: int var; static int& varAccessor( A& a ) { return a.var; } }; 然后在派生类型中调用受保护的访问者通过引用传递成员对象: varAccessor( this->myA ) = 5; 现在,如果您正在考虑装饰器模式,我认为这不是可行的方法.混淆的根源在于大多数人没有意识到类型有两个独立的接口,即面向用户的公共接口和实现提供者的虚拟接口(即派生类型),因为在许多情况下,功能都是公共的和虚拟的(即该语言允许绑定两个语义不同的接口).在Decorator模式中,您使用基接口来提供实现.继承是存在的,因此派生类型可以通过一些实际工作(装饰)为用户提供操作,然后将工作转发到实际对象.继承关系不是通过受保护元素以任何方式访问实现对象的,并且这本身就很危险.如果传递一个派生类型的对象,该对象具有关于该受保护成员的更严格的不变量(即对于类型为X的对象,var必须是奇数),您正在采用的方法将让装饰器(各种类型)打破不变量应该只是装饰的那种X型. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- c – 如何在其默认程序中打开文件
- c# – ELMAH – 是否记录引用URL
- net.sf.json.JSONException: There is a cycle in the hier
- c# – 使用Powershell调用WCF服务方法
- ios – ObjC Plist文件读取比JSON更快?
- Ajax POST调用ASP.NET MVC控制器给出net :: ERR_CONNECTION
- ruby-on-rails – 将Jasper集成到Rails 3中
- 是否有一个与ruby 1.9.2一起使用的soap4r / wsdl2ruby版本?
- @JsonInclude(Include.NON_NULL)
- 连接远程postgresql