【问题标题】:Operator overloads within a class heirarchy类层次结构中的运算符重载
【发布时间】:2020-09-14 23:23:54
【问题描述】:

抱歉,如果之前有人问过并回答过这个问题,但我一直在寻找一个可以理解的解决方案几个小时,但没有任何乐趣。

我正在尝试使用在基类中定义的运算符重载来实现一个简单的类层次结构(因为这些在各种派生类之间不会有所不同)。但是,由于其中大多数都需要返回我们在上下文中的任何派生类的新对象,我假设它们需要声明为模板化方法,但是,当我尝试编译这样做时,链接器给了我一个“未解析的外部符号”错误...

举个例子:

/// 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++ 中根本没有简单的方法来做到这一点?

【问题讨论】:

  • 您正在与operator+(const T&amp; lhs, const T&amp; rhs) 成为任何T 的朋友,不确定这是不是个好主意。除其他外,这为任何人访问私人成员打开了一扇门。无论如何,我认为这是你的直接问题:stackoverflow.com/questions/495021/…
  • 这确实是问题所在。另请注意下面 Human-Compiler 的答案,该答案还概述了如何使运算符类型安全。自从我对 C 或 C++ 做任何严肃的事情以来已经有好几年了,所以这一切就像试图再次从头开始学习一门外语......

标签: c++ inheritance visual-c++ operator-overloading


【解决方案1】:

您的评论指出模板的“在实施文件中”,这可能是您的问题的原因。函数模板声明(例如T operator+(const T&amp;, const&amp;); 声明必须链接的符号——但它需要在某处对该模板进行实例化

在源文件中简单地定义template 函数实际上并没有实例化代码——它需要明确地对希望链接的每种类型进行具体实例化,或者让函数模板定义从打算调用它的地方(有关详细信息,请参阅this answer)。

在许多情况下,最好在头文件中定义函数模板,以便模板的任何调用者都能够实例化函数,而无需链接到其他地方的现有实例。


也就是说……

您可能需要重新考虑当前的方法。您的operator+ 模板不限制可以考虑的T 类型,这将导致operator+(const T&amp;, const T&amp;) 成为任何 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);
}

【讨论】:

  • 非常感谢。这确实是问题所在。还要感谢有关类型检查运算符的指针。一旦我的基本功能正常工作,那是我议程上的下一个项目:)
猜你喜欢
  • 1970-01-01
  • 2013-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-24
  • 1970-01-01
相关资源
最近更新 更多