2013-04-25 96 views
1

很抱歉的坏称号基类的赋值运算符......我有一个基类,如:我可以在返回子类类型

template<class T> 
class GPtr 
{ 
public: 
    typedef T BaseType; 

    GPtr& operator=(const BaseType& rhs) 
    { 
     ... 
    } 
}; 

我经常想使子类的专门化,如:

class GraphicPtr : public GPtr<Graphic> 
{ 
... 
}; 

但是我的基类赋值运算符仍返回GPtr<Graphic>没有GraphicPtr,它的恼人必须复制粘贴代码的情况下,核心赋值运算符的功能应该在以后更改。

是否有一种简洁的方式来定义基类赋值运算符,以便返回正在使用的实际类的类型?

+0

为什么不写函数,真的可以在所有派生类中进行赋值和调用? – ForEveR 2013-04-25 09:08:12

+0

这里解决的真正问题是什么?不是解决方案的语法问题,而是解决方案似乎具有返回对派生类型的引用的赋值运算符的实际问题。有几件事情不清楚,比如为什么'GPtr <> :: operator ='接受一个'T'参数(错误地命名为'BaseType'),你想达到什么目的? – 2013-04-25 13:12:45

回答

1

在C++中,基类不知道它的子类。您可以添加一个将作为派生类的模板参数并使用它。

template<class T, class Derived> 
class GPtr 
{ 
public: 
    typedef T BaseType; 

    Derived& operator=(const BaseType& rhs) 
    { 
     ... 
    } 
}; 
+0

我想知道这是否可能。但是,如果我想直接使用'GPtr',但不总是在子类中,会发生什么? – 2013-04-25 09:15:15

+0

我试图使第二个参数GPtr ,但它是不可能的,因为在这里我们需要无限的专业化:GPtr >>>。也许在这里你应该尝试不同的东西:) – lisyarus 2013-04-25 09:32:51

+1

这就是我看到的同样的问题。它似乎应该是可能的东西,但我不太了解模板 – 2013-04-25 09:34:56

1

也许你可以用CRTP代替?

#include <iostream> 

template<class Derived> 
class GPtr 
{ 
public: 
    typedef Derived DerivedType; 

    GPtr& operator=(const GPtr& rhs) 
    { 
     std::cout << "GPtr::operator=" << std::endl; 

     return *this; 
    } 
}; 

class GraphicDerived : public GPtr<GraphicDerived> 
{ 
    public: 

     GraphicDerived& operator=(const GraphicDerived& rhs) 
     { 
      std::cout << "GraphicDerived::operator=" << std::endl; 
      // Inheiriting shadows the name of the base operator= which 
      // needs to be explicitly called. 
      GPtr<GraphicDerived>::operator=(rhs); 
      return *this; 
     }; 
}; 

class Graphic {}; 

using namespace std; 

int main() 
{ 


    GraphicDerived one; 
    GraphicDerived two; 

    cout << "derived assignment: " << endl; 
    one = two; 

    GPtr<Graphic> ptrOne; 
    GPtr<Graphic> ptrTwo; 

    cout << "GPtr assignment stnadalone : " << endl; 

    ptrOne = ptrTwo; 
}; 

结果与:

derived assignment: 
GraphicDerived::operator= 
GPtr::operator= 
GPtr assignment stnadalone : 
GPtr::operator= 
+0

也许我误读,但似乎有两个问题... 1)我仍然必须在派生类中编写一个单独的赋值运算符... 2)基数类已经在它包装的类型上模板化,它与子类 – 2013-04-25 09:34:02

+1

不相同。1)如果派生类与基类相比具有附加属性,则在派生类中添加单独的赋值运算符是有意义的。 2)好吧,我明白你的意思了,这里有个反问题:你究竟想达到什么目的? – tmaric 2013-04-25 09:37:42

1

你所要求的并没有真正意义。在分配基础对象时,它不可能知道它被调用的派生类型中可能有无限多个派生类型,因此无法在每种情况下返回不同的类型。此外,即使这是可能的,也不可能在真实的代码中使用它。

C++解决一切,但在运行时多态性电话,甚至多态调用它只是延迟找到确切覆盖,但没有签名(即即使协变返回类型,基本覆盖的返回类型将被使用。

从技术上讲,可以使用或不使用模板,所有这些都表现出相同的核心问题:基类只能是单一类型的基类,由赋值运算符返回的类型,限制可用性为基地类。

你想解决什么是真正的问题?

您采取的方法似乎不合适。如果你解释了你正在努力达到的目标,那么人们可以建议其他方法会更好。

+0

正是我所评论的。我以为我错过了一些东西。 1+。 – tmaric 2013-04-25 12:05:00

+0

尽管这不是一个正常的继承,但它是模板化的 - 所以对于每个特定的变体,都会创建一个完全独立的类,而不是具有真正的基类方法。因此赋值运算符在每种情况下都是相同的,适用于涉及的模板类型。 @lisyarus'的答案与我所做的最接近 – 2013-04-25 14:42:26

+0

@John:它是否是模板几乎是正交的。没有任何东西可以抑制'struct a:base {}; struct b:base {};'。除非这个限制是你设计的一部分(你可以在C++ 11中强制执行,但是不会在你的代码中执行)。如果是这样的话,那么你就是在滥用继承,并且应该用组合来代替,没有理由不将'GPtr '作为'GraphicDerived'的成员,并且我仍然没有看到赋值......隐式定义的不工作的原因是什么? (为什么?) – 2013-04-25 15:52:04