简体   繁体   English

class 层次结构中的运算符重载

[英]Operator overloads within a class heirarchy

Apologies if this has been asked and answered before, but I've been searching for an understandable solution now for hours with no joy.抱歉,如果之前有人问过并回答过这个问题,但我现在一直在寻找一个可以理解的解决方案几个小时,但没有任何乐趣。

I'm trying to implement a simple class hierarchy with operator overloads defined within the base class (since these will not differ between the various derived classes).我正在尝试实现一个简单的 class 层次结构,其中在基 class 中定义了运算符重载(因为这些在各种派生类之间不会有所不同)。 However, since most of these will need to return a new object of whatever derived class we're in the context of, I'm assuming they need to be declared as a templated method, however, when I attempt to compile doing this, the linker gives me an 'Unresolved external symbol' error...但是,由于其中大部分都需要返回一个新的 object,无论我们在上下文中派生什么 class,我假设它们需要被声明为模板化方法,但是,当我尝试这样做编译时, linker 给我一个“未解析的外部符号”错误...

By way of an example:举个例子:

/// 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);
}

I was hoping that this would lead to my being able to declare derived objects thus:我希望这会导致我能够这样声明派生对象:

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;

Is the desired outcome, but short of defining the operators within each individual derived class, I cannot see a way I can implement this in C++ since the Template approach leads to the linker error.是期望的结果,但没有在每个派生的 class 中定义运算符,我看不到我可以在 C++ 中实现它的方法,因为模板方法会导致 linker 错误。

Am I missing something blindingly obvious and fundamental, or is there simply no easy way of doing this in C++?我是否遗漏了一些非常明显和基本的东西,或者在 C++ 中根本没有简单的方法可以做到这一点?

Your comment indicates "in the implementation file" for the template, which is likely the cause of your issue.您的评论表明模板“在实施文件中”,这可能是您问题的原因。 Function template declarations (eg T operator+(const T&, const&); declare the symbols that must be linked against -- but it requires an instantiation of that template somewhere. Function 模板声明(例如T operator+(const T&, const&);声明必须链接的符号——但它需要在某处实例化该模板。

Simply defining the template function in the source file doesn't actually instantiate the code -- it requires either concrete instantiations of each type explicitly that is desired to be linked against, or to have the function template definition visible from the place that intends to call it (see this answer for more detail).简单地在源文件中定义template function 并不会实际实例化代码——它需要明确需要链接的每种类型的具体实例化,或者使 function 模板定义从打算调用的地方可见它(有关更多详细信息,请参见此答案)。

In many cases, it's better to define the function template in a header file, so that any callers of the template will be able to instantiate the functions without requiring linking against an existing instantiation elsewhere.在许多情况下,最好在 header 文件中定义 function 模板,这样模板的任何调用者都可以实例化函数,而无需链接到别处的现有实例化。


That said...那说...

You might want to re-think your current approach.您可能需要重新考虑当前的方法。 Your operator+ template does not constrain what type T can be considered, which will cause operator+(const T&, const T&) to be a viable overload for any T type that does not already have an operator+ provided that the declaration is visible during overload resolution.您的operator+模板不限制可以考虑哪种类型T ,这将导致operator+(const T&, const T&)对于任何尚不具有operator+T类型都是可行的重载,前提是声明在重载解析期间可见。 This may lead to other strange compiler / linker errors.这可能会导致其他奇怪的编译器/linker 错误。

There are several ways to address constraining the type;有几种方法可以解决约束类型的问题; probably the simplest one would be to use SFINAE to constrain it by checking that T is derived from Base .可能最简单的方法是使用 SFINAE 通过检查T是否派生自Base来约束它。

For example:例如:

/// 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM