开发者

How to avoid C++ cast for specific class methods? Design Pattern?

开发者 https://www.devze.com 2023-02-19 12:48 出处:网络
Suppose I have something like this: class Father { public: virtual int genericMethod (void) =0; }; class Son1: public Fa开发者_如何学Pythonther {

Suppose I have something like this:

class Father {
    public:
      virtual int genericMethod (void) =0;
  };

class Son1: public Fa开发者_如何学Pythonther {
  public:
    int genericMethod ()
      { }
  };

class Son2: public Father {
  public:
    int genericMethod ()
      { }
    int specifClassMethod()
      { }
  };

In the main I do the following:

Father * test = new Son2();

test->specifClassMethod(); //Can't do this! It is specific of Class Son2 and is not a virtual method in class Father!

The main question here is to know the better way to access Son2 specific method through Father interface. I want to know if there is a Design Pattern to solve this or another way. I don't wanna to do casts and I don't wanna to put lots of 'if' in my code.

Regards,

Eduardo


Maybe the Visitor-Pattern is the pattern you're looking for.

How Visitor Pattern avoid downcasting


Possible approach is to have specific interface with optional methods, and virtual method to get this interface in the base class (which may return zero):

class SpecificInterface {
public:
  virtual ~SpecificInterface()
  { }
  virtual int specifClassCmethod() = 0;
  { }
};

class Father {
  public:
    virtual int genericMethod (void) = 0;
    virtual SpecificInterface* getSpecificInterface (void) =0;
};

class Son1: public Father {
  public:
    int genericMethod ()
      { }
    SpecificInterface* getSpecificInterface (void)
      { return 0; }
  };

class Son2: public Father, public SpecificInterface {
  public:
    int genericMethod ()
      { }
    int specifClassCmethod()
      { }
    SpecificInterface* getSpecificInterface (void)
      { return this; }
  };

Usage is following:

Father * test = new Son1();
SpecificInterface * specificAPI = test->getSpecificInterface();
if( specificAPI )
  specificAPI->specifClassCmethod();


You couldn't legally solve this with a cast, either, because "test" is pointing to a Father object, not a Son2 object. Casting object types means "Trust me, compiler, this variable actually holds X". It doesn't somehow magically convert a base object into a derived object; it only tells the compiler something you already know that it does not.

If you want behavior that differs by derived class, then move the behavior into a virtual method -- i.e., the code that wants to call specificCLassMethod() belongs in a virtual method of Father.


No. To call methods which only exist in a child class, you'll have to cast to the ch ild class.

While you could create a map which maps function names to functions, add your functions to it from the child class' constructor and then use something like test->callMethod("name"); you'd have to make all those methods have the same signature or use varargs to pass arguments which is not very nice.


You can static_cast<Son2*>(test)->specifClassCmethod(); but that only works if Father * test = new Son2();


If you really have something specific to Son2 then dynamic_cast<> is what you should use. If it is something that could be added as a virtual function to the base class with a default empty behaviour, then you can solve your issue without a cast (but that is not what you wanted to do as you stated in the question)

One design pattern to solve your issue is to use a proxy object. That object would have all the methods susceptible to be called and delegate them to the real object or not.

Advantages of the proxy pattern:

  • you concentrate the logic needed to differentiate the objects behind to one place
  • you can add some logging easily
  • the client code remains simple and the Son classes clean from extra stuff


First of all,you can not create an instance for the class "Father" because it is an abstract class(which has virtual int genericMethod (void) =0; -pure virtual function).Instead an instance can be assigned to it....

Like

Son1* obj_son = new Son1();
Father* obj = obj_son;
//now if you call generic method - son1 method will be called(Father method is over ridden)
obj->genericMethod();
//similarly for son2 class
Son2* obj_son2 = new Son2();
Father* obj2 = obj_son2;
obj2->genericMethod();
obj2->specifClassCmethod();
0

精彩评论

暂无评论...
验证码 换一张
取 消