基类中的重载方法,默认情况下具有成员变量 [英] Overloading method in base class, with member variable as default

查看:96
本文介绍了基类中的重载方法,默认情况下具有成员变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的类结构如下:

class Base {
    public:
        void setDefault( uint8_t my_default ) { m_default = my_default; }

        void method( uint8_t * subject ) { method( subject, m_default ); }
        virtual void method( uint8_t * subject, uint8_t parameter ) =0;

    protected:
        uint8_t m_default;
};

class Derived1 : public Base {
    public:
        void method ( uint8_t * subject, uint8_t parameter ) { /* do something to subject */ }
};

class Derived2 : public Base {
    public:  
        void method ( uint8_t * subject, uint8_t parameter ) { /* do something different to subject */ }
};

我希望能够在从Base派生的类的任何实例上调用method( ... ),这将使用成员变量作为默认参数来调用派生类中定义的方法.

I want to be able to call method( ... ) on any instance of a class derived from Base, which will call the method defined in the derived class using the member variable as the default parameter.

根据我在Stack Overflow上其他地方所读到的内容

From what I've read elsewhere on Stack Overflow here, the override must have the same signature, which is why it won't compile.

这种方法是否存在潜在的歧义?

Are there any potential ambiguities with this approach?

我可以通过两种方法解决此问题:

Two ways I can think to get around this:

  1. 为每个派生类声明一个默认的method( void ),但这似乎不太干
  2. 为默认方法使用其他名称(例如defaultMethod( uint8_t * subject )),但我认为这会使我的课程不太直观
  1. declare a default method( void ) for each derived class, but this doesn't seem very DRY
  2. use a different name for the default method (e.g. defaultMethod( uint8_t * subject )) but I feel this makes my class less intuitive

有没有更好的办法解决这个问题?

Is there a better way around this?

这是一个完整的示例,无法编译(Arduino IDE 1.7.9):

Here is a complete example, which won't compile (Arduino IDE 1.7.9):

class Base {
    public:
        void setDefault( uint8_t my_default ) { m_default = my_default; }

        void method( uint8_t * subject ) { method( subject, m_default ); }
        virtual void method( uint8_t * subject, uint8_t parameter ) =0;

    protected:
        uint8_t m_default;
};

class Derived1 : public Base {
    public:
      void method ( uint8_t * subject, uint8_t parameter ) { *subject += parameter; }
};

class Derived2 : public Base {
    public:  
      void method ( uint8_t * subject, uint8_t parameter ) { *subject *= parameter; }
};

Derived1 derived1;
Derived2 derived2;

uint8_t subject = 0;

void setup() {
  // put your setup code here, to run once:
  derived1.setDefault( 3 );
  derived2.setDefault( 5 );
}

void loop() {
  // put your main code here, to run repeatedly:
  derived1.method( &subject, 1 );  // subject == 1  
  derived2.method( &subject, 2 );  // subject == 2  

  // won't compile with this line:
  derived1.method( &subject );  // subject == 5
}

产生的错误是:

over-ride-load.ino: In function 'void loop()':
over-ride-load.ino:39:29: error: no matching function for call to 'Derived1::method(uint8_t*)'
over-ride-load.ino:39:29: note: candidate is:
over-ride-load.ino:14:12: note: virtual void Derived1::method(uint8_t*, uint8_t)
over-ride-load.ino:14:12: note:   candidate expects 2 arguments, 1 provided
Error compiling.

推荐答案

我相信您正在寻找的是using指令.

What I believe that you're looking for is the using directive.

您已正确完成Base中的所有操作.尽管使用默认参数通常比定义第二个函数更好,但鉴于您的要求(使用成员)在这里是不可能的:因此,您定义了第二个重载函数来对其进行修复(并将其定义为inline-荣誉!)

You've done everything correctly in Base. While using a default parameter is (often) better than defining a second function, given your requirements (using a member) that's not possible here: so you defined a second overloaded function to fix it (and defined it inline - kudos!).

但是问题来自派生类.如果您不重写虚拟函数,那么一切都会很好:method的两个版本都可以使用.但是您必须覆盖它,因此您必须用method(subject,parameter);有效地掩盖" method(subject);的基本版本.

But the problem comes with the derived classes. If you didn't override the virtual function, everything would have been fine: both versions of method would be available to you. But you have to override it, so you effectively "mask" the base version of method(subject); with method(subject,parameter);.

您想要做的是将所有Basemethod提升"到各个Derived中,以使它们具有相等的权重.如何?使用using指令.

What you want to do is "promote" all of Base's methods into the various Deriveds, to give them equal weighting. How? With the using directive.

在每个Derived定义中,输入以下代码:

In each Derived definition, put the following code:

using Base::method;

这会将Base的所有方法提升"到Derived中-同时仍然允许您覆盖单个方法.我建议您将该行直接放在每个Derivedmethod()替代上方.

That "promotes" all of Base's method into the Derived - while still allowing you to override individual ones. I suggest that you put that line directly above each Derived's method() override.

这篇关于基类中的重载方法,默认情况下具有成员变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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