考虑两个类class B
和class C
,每个类都有一个int
类型private
成员,一个将int
成员设置为零的构造函数,以及operator++()
成员函数,B b; ++b
将int
成员增加1,C c; ++c
将成员增加10.这是多态性的典型示例。我们可以从公共抽象基础class B
派生class C
和class A
,它具有纯虚拟成员函数operator++()=0
。在为operator++()
和class B
定义具体的class C
函数后,我们可以使用A& a=b; ++a
来增加int
成员{} {}按1,a
将A& 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 C
是class B
,它会被转换为++a
然后int
,而是直接如果++
是a
?
B
答案 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)
如果要在运行时确定子类类型,即a
是B
还是a
是C
在编译时是不知道的,那么似乎在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 ++版本可能需要丰富其变体类型(在运行时确定的类型)机制。