可以通过隐式类型转换实现虚函数吗?或者我如何进行子类依赖类型转换?

时间:2016-08-30 09:12:07

标签: c++ inheritance polymorphism type-conversion

考虑两个类class Bclass C,每个类都有一个int类型private成员,一个将int成员设置为零的构造函数,以及operator++()成员函数,B b; ++bint成员增加1,C c; ++c将成员增加10.这是多态性的典型示例。我们可以从公共抽象基础class B派生class Cclass A,它具有纯虚拟成员函数operator++()=0。在为operator++()class B定义具体的class C函数后,我们可以使用A& a=b; ++a来增加int成员{} {}按1,aA& a=c; ++a增加10。

现在情况稍微复杂一些。假设我们有

a

这样 class B{ private: int n; public: B(int b=0) {n=b;} void output() {cout<<n<<endl;} operator int&() {return n;} }; class C{ private: int n; public: C(int c=0) {n=c;} void output() {cout<<n<<endl;} C& operator++() {n+=10; return *this;} }; 操作不是由成员函数B b; ++b完成的,而是通过operator++()b对其内部{int&的引用的隐式类型转换。 1}}成员,然后是int类型的++运算符。然后我发现多态性不再有效。

int

以上代码仅适用于 class A{ protected: int n; public: A(int a=0) {n=a;} void output() {cout<<n<<endl;} virtual A& operator++()=0; }; class B:public A{ public: operator int&() {return n;} }; class C:public A{ public: C& operator++() {n+=10; return *this;} }; ,但不适用于A& a=c; ++a。公共基础A& a=b; ++a的纯虚operator++()=0继承到class A并保持纯虚拟,因此class B变为抽象,无法再定义任何对象,即使{ {1}}实际上可以通过类型转换来实现。

假设类依赖类型转换是我想要的一些功能,因为转换可能很昂贵而且我不希望它发生在class B,但不知怎的,我别无选择,只能为{ {1}}。我希望通过使用某种“多态”来使我的代码变得聪明(即使直接在这里失败)。有没有人看到在C ++中进行这种子类依赖类型转换的方法?我的意思是,当我++b时,如果class Cclass B,它会被转换为++a然后int,而是直接如果++a

,则会员函数B

2 个答案:

答案 0 :(得分:1)

您可以通过CRTP

执行此操作

示例:

template <class T>
class Base
{
private:
    int n;
public:
    T& operator++() {n+=10; return *this;}
    ...
};

class C : public Base<C>
{
    ...
};

注意:这仅适用于代码重用,并且没有公共基类(因为每个基因类都不同)

如果你需要一个共同的基类,你可以通过3个类

来完成
class Base
{
protected:
    int n;
};


template <class T>
class BaseOperator : public Base
{

public:
    T& operator++() {n+=10; return *this;}
};

class C : public BaseOperator<C>
{
    ....
};

答案 1 :(得分:0)

如果要在运行时确定子类类型,即aB还是aC在编译时是不知道的,那么似乎在C ++中还没有允许这种依赖于子类的类型转换的机制。即使以下代码也不起作用:

  #include <iostream>
  using namespace std;

  class B{
    protected:
      int n;
    public:
      B(int b=0) {n=b;}
      void output() {cout<<n<<endl;}
      operator int&() {return n;}
  };

  class C: public B{
    public:
      C& operator++() {n+=10; return *this;}
  };

  int main(){
    B b; C c; ++b; b.output(); ++c; c.output();
    B& a1=b; ++a1; B& a2=c; ++a2;
    a1.output(); a2.output(); return 0;
  }

此代码尝试使用成员函数重写类型转换的机制。它适用于++b++c以及++a1,但不适用于++a2。尽管a2实际上是C,但编译器在编译时并不知道,因此a2仍然首先被类型转换为int&然后{{1}编辑,即编译器仍然将++视为a2,即使它实际上是B

虚函数机制只能动态决定调用哪个函数版本,但不能选择完全避免调用该函数并用其他函数取代它。因此即使将C添加到virtual的{​​{1}},operator int&()仍然会被转换为class B,因为a2没有class B它的类型转换的新定义。未来的C ++版本可能需要丰富其变体类型(在运行时确定的类型)机制。