如何避免 C++为特定的类方法进行强制转换?设计模式?

发布于 2024-10-26 10:45:32 字数 634 浏览 1 评论 0原文

假设我有这样的事情:

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

class Son1: public Father {
  public:
    int genericMethod ()
      { }
  };

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

主要我做了以下事情:

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!

这里的主要问题是知道通过 Father 接口访问 Son2 特定方法的更好方法。我想知道是否有设计模式可以解决这个问题或其他方法。我不想进行强制转换,也不想在代码中添加大量“if”。

问候,

爱德华多

Suppose I have something like this:

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

class Son1: public Father {
  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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

书间行客 2024-11-02 10:46:42

首先,您不能为“Father”类创建实例,因为它是一个抽象类(具有 virtual int genericMethod (void) =0; -pure virtual function)。相反,可以为其分配一个实例。 ..

喜欢

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();

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();
千鲤 2024-11-02 10:46:35

如果您确实有特定于 Son2 的内容,那么您应该使用 dynamic_cast<>。如果它可以作为虚拟函数添加到具有默认空行为的基类中,那么您可以在不进行强制转换的情况下解决您的问题(但这不是您在问题中所述的想要做的事情)

一种设计解决您的问题的模式是使用 代理对象。该对象将具有易于调用的所有方法,并将它们委托给真实对象或不委托给真实对象。

代理模式的优点:

  • 您将区分后面的对象所需的逻辑集中到一个地方,
  • 您可以轻松添加一些日志记录,
  • 客户端代码保持简单,并且 Son 类没有多余的东西

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
许久 2024-11-02 10:46:27

您可以 static_cast(test)->specifClassCmethod(); 但这仅在 Father * test = new Son2(); 时有效

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

清风挽心 2024-11-02 10:46:18

不可以。要调用仅存在于子类中的方法,您必须强制转换为子类。

虽然您可以创建一个将函数名称映射到函数的映射,但可以从子类的构造函数中将函数添加到其中,然后使用类似 test->callMethod("name"); 的内容必须使所有这些方法具有相同的签名或使用可变参数来传递参数,这不是很好。

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.

那小子欠揍 2024-11-02 10:46:05

您也无法通过强制转换合法地解决此问题,因为“测试”指向 Father 对象,而不是 Son2 对象。转换对象类型意味着“相信我,编译器,这个变量实际上保存着 X”。它不会以某种方式神奇地将基础对象转换为派生对象;而是将其转换为派生对象。它只告诉编译器一些你已经知道但它不知道的事情。

如果您希望派生类具有不同的行为,则将该行为移至虚拟方法中——即,想要调用特定CLassMethod() 的代码属于Father 的虚拟方法。

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.

又怨 2024-11-02 10:45:55

可能的方法是拥有带有可选方法的特定接口,以及在基类中获取此接口的虚拟方法(可能返回零):

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

用法如下:

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

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();
握住我的手 2024-11-02 10:45:44

也许访问者模式就是您正在寻找的模式。

访问者模式如何避免向下转型

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

How Visitor Pattern avoid downcasting

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文