在类的继承结构中的操作符重载。

问题描述 投票:0回答:1

如果这个问题之前已经有人问过并回答过,我表示歉意,但我现在一直在寻找一个可以理解的解决方案,但没有任何乐趣。

我正试图实现一个简单的类层次结构,在基类中定义了操作符重载(因为这些操作符在不同的派生类之间不会有区别)。 然而,由于这些操作符大多需要返回一个新的对象,无论我们在哪个派生类的上下文中,我假设它们需要被声明为一个模板方法,然而,当我试图这样编译时,链接器给了我一个 "未解决的外部符号 "错误......

举个例子。

/// This is in the class header file
class Base
{
   // Declare all the base storage and methods ...

public:
   template<class T>
   friend T operator+(const T& lhs, const T& rhs);

   // .... other stuff in here.
}


/// Then in the implementation file
T operator+ (const T& lhs, const T& rhs)
{
   return T(lhs->m_1 + rhs->m_1, lhs->m_2);
}

我希望这将导致我可以这样声明派生对象。

class Derived : public Base
{
   // ... Add the derived class functionality

   // -- Question:  Do I need to do anything in here with operator+ ???
}
Derived A();
Derived B();

Derived C = A + B;

这就是我所希望的结果 但如果不在每个派生类中定义操作符 我就无法在C++中实现这个功能 因为模板方法会导致链接器错误

是我遗漏了一些显而易见的根本性的东西,还是在C++中根本没有简单的方法来实现这个功能?

c++ inheritance visual-c++ operator-overloading
1个回答
2
投票

你的评论中指出了模板的 "实现文件中",这很可能是你的问题的原因。函数模板声明(如 T operator+(const T&, const&); 声明必须与之链接的符号--但它需要一个 实例化 的某处。

只需简单地定义该模板的 template 源文件中的函数实际上并不实例化代码 -- 它需要明确地对每个类型的具体实例进行链接,或者在打算调用它的地方有可见的函数模板定义(见 本回答 了解更多细节)。)

在很多情况下,最好是在头文件中定义函数模板,这样模板的任何调用者都可以实例化函数,而不需要与其他地方的现有实例进行链接。


也就是说...

你可能需要重新考虑一下你目前的做法。你的 operator+ 模板不限制什么类型的 T 可以考虑,这将导致 operator+(const T&, const T&) 是一个可行的过载 任何 T 类型,但还没有一个 operator+ 但前提是在重载解析期间声明是可见的。这可能会导致其他奇怪的编译器链接器错误。

有几种方法可以解决约束类型的问题;最简单的方法可能是使用SFINAE来约束它,通过检查 T 源于 Base.

例如:

/// This is in the class header file
class Base
{
   // Declare all the base storage and methods ...

public:
   template<class T, class>
   friend T operator+(const T& lhs, const T& rhs);

   // .... other stuff in here.
}


// Note: In the same header!
// This only enables + if 'T' derives from 'Base'
template <typename T, typename = std::enable_if_t<std::is_base_of<Base,T>::value>>
T operator+(const T& lhs, const T& rhs)
{
   return T(lhs->m_1 + rhs->m_1, lhs->m_2);
}
© www.soinside.com 2019 - 2024. All rights reserved.