假设我们有两个类:
class DataStructure {
public:
DataStructure &operator=(const DataStructure &);
friend const DataStructure &operator+(int, const DataStructure &);
//...
};
class Array : public DataStructure {
public:
Array &operator=(const DataStructure &);
friend const Array &operator+(int, const Array &);
//...
};
我们希望Array::operator=
和Array
的朋友operator+
与DataStructure::operator=
和DataStructure
的朋友operator+
做同样的事情。 ,除了他们应该返回Array &
,const Array &
而不是DataStructure &
,const DataStructure &
。我需要使用几十种方法来实现它,那么实现它的方法是否比以下更简单?
Array &Array::operator=(const DataStructure &other) {
return (Array &)DataStructure::operator=(other);
}
const Array &operator+(int x, const Array &other) {
return (const Array &)(x + (DataStructure)other);
}
编辑:我提出了另一个想法,虽然这是一个非常糟糕的想法:
class Array;
class DataStructure {
public:
//...
operator Array &() const;
};
//...
DataStructure::operator Array &() const {
return (Array &)*this;
}
这种方式DataStructure
会在需要时隐式转换为Array
,但仍然无法正确处理DataStructure
和Array
合法但不同的情况事情,如本例所示:
//in class DataStructure:
public:
friend ostream &operator<<(ostream &os,const DataStructure &)
{ os << "DataStructure" << endl; return os;}
//in class Array:
public:
friend ostream &operator<<(ostream &os,const Array &)
{ os << "Array" << endl; return os;}
//...
int main() {
Array x;
cout << 1 + x << endl;
// output: "DataStructure" instead of "Array"
return 0;
}
谢谢!
答案 0 :(得分:1)
您的实现不好:operator=
应该返回对Array类型的对象的引用,而不应该是虚拟的:
Array &Array::operator=(const DataStructure &other) {
DataStructure::operator=(other);
return *this;
}
您可以将DataStructure
更改为使用NVI:
#include <iostream>
class DataStructure {
public:
DataStructure(){}
inline virtual ~DataStructure(){}
DataStructure &operator=(const DataStructure & other);
inline friend const DataStructure &operator+(const int a, const DataStructure & other)
{ other.add(a); return other; }
//...
private:
virtual void add( const int a ) const = 0;
};
struct Array : DataStructure
{
virtual void add( const int a ) const
{
std::cout<<"adding "<<a<<std::endl;
}
};
void foo(const DataStructure &a)
{
const DataStructure &b = 5 + a;
}
int main()
{
Array a;
foo(a);
}
检查live demo。然后,您必须在派生类Array中实现方法add
。
进行编辑:
你的新想法是用c ++做事的糟糕方式。你在那里做的是告诉你的编译器:“停止抱怨,我知道我在做什么”。此外,它会导致未定义的行为。它似乎可以工作,直到你的应用程序开始崩溃一天。
答案 1 :(得分:0)
最终我设法找到答案。对于operator=
:
class Array : public DataStructure {
public:
//...
using DataStructure::operator=;
Array &operator=(const DataStructure &);
};
仅写Array &operator=(const DataStructure &);
会隐藏DataStructure::operator=
,但使用using
语句只会更改方法的返回类型。
注意: using
语句必须位于第Array &operator=(const DataStructure &);
行之前,否则operator=
将不明确。
至于operator+
,我找到的唯一解决方案是非常有问题的。它使用模板:
public DataStructure {
public:
template<class T> friend const T &operator+(int, const T &);
};
例如,如果原始实现是
const DataStructure &operator+(int x, const DataStructure &other) {
DataStructure addition(other); /* in this example we assume
* that "DataStructure" isn't abstract */
addition.someParameter += x; /* for simplicity, assume that
* "someParameter" is public/protected */
return addition;
}
我们希望获得与
相同的结果const Array &operator+(int x, const Array &other) {
return (const Array &)(x + (DataStructure)other);
}
我们可以简单地写一下:
template<class T>
const T &operator+(int x, const T &other) {
DataStructure addition(other); /* notice that usually we would want
* to write "T" instead of "DataStructure", but sometimes it would
* give a different result */
addition.someParameter += x;
return (const T &)addition;
}
但是,如果存在与operator+(int,/*const*/ ThirdClass /*&*/)
或DataStructure
无关的函数Array
,则我们必须更改它,这可能会使代码陷入混乱。幸运的是,通常只有一些朋友函数,所以实现一个执行转换的新方法(如问题所示)并不是那么糟糕。