从嵌套结构继承:模板和指针
我正在尝试向 C++ 中的嵌套结构添加一些额外的字段,并且设计表明我想通过继承来执行此操作。我收到一个错误,奇怪的是,该错误取决于我使用的是 T* 类型还是 T** 类型。我很困惑,希望有人帮助我了解这里发生的事情。
嵌套结构是 Base::Node,我想向 Base::Node 添加一个字段 b,然后使用 Derived,如 main 中所示。当我将顶部的 #define 设置为 0 时,一切都会编译并正常工作。当我将 #define 更改为 1 时,出现以下编译器错误:
main_inhtest.cpp: In instantiation of ‘Derived<int>’:
main_inhtest.cpp:52: instantiated from here
main_inhtest.cpp:44: error: conflicting return type specified for ‘Derived<T>::DNode** Derived<T>::GetNAddr() [with T = int]’
main_inhtest.cpp:24: error: overriding ‘Base<T>::Node** Base<T>::GetNAddr() [with T = int]’
main_inhtest.cpp: In member function ‘Derived<T>::DNode** Derived<T>::GetNAddr() [with T = int]’:
main_inhtest.cpp:57: instantiated from here
main_inhtest.cpp:44: error: invalid static_cast from type ‘Base<int>::Node**’ to type ‘Derived<int>::DNode**’
有人可以帮助我理解
这是否是执行此操作的正确方法,以及是否有更好的方法,以及
为什么编译器对 GetN() 方法感到满意,但对 GetNAddr() 方法不满意?
谢谢!
#include <iostream>
#define TRY_GET_N_ADDR 1
template <typename T> class Base {
public:
Base() { n = new Node(); }
struct Node
{
T a;
};
virtual Node *GetN() { return n; }
virtual Node **GetNAddr() { return &n; }
Node *n;
};
template <typename T> class Derived : public Base<T> {
public:
Derived() { Base<T>::n = new DNode(); }
struct DNode : Base<T>::Node
{
T b;
};
// This method is fine
DNode *GetN() { return static_cast<DNode *>(Base<T>::GetN()); }
#if TRY_GET_N_ADDR
// Compiler error here
DNode **GetNAddr() { return static_cast<DNode **>(Base<T>::GetNAddr()); }
#endif
};
int main (int argc, const char * argv[]) {
Derived<int> d;
d.GetN()->a = 1;
d.GetN()->b = 2;
std::cout << d.GetN()->a << " " << d.GetN()->b << std::endl;
}
I am trying to add some additional fields to a nested struct in C++, and the design dictates that I want to do so via inheritance. I'm getting an error that curiously depends on whether I'm working with type T* or type T**. I'm fairly confused and would appreciate somebody helping me to understand what's happening here.
The nested struct is Base::Node, and I want to add a field, b, to Base::Node then use Derived as shown in the main. When I set the #define at the top to 0, everything compiles and works fine. When I change the #define to 1, I get the following compiler error:
main_inhtest.cpp: In instantiation of ‘Derived<int>’:
main_inhtest.cpp:52: instantiated from here
main_inhtest.cpp:44: error: conflicting return type specified for ‘Derived<T>::DNode** Derived<T>::GetNAddr() [with T = int]’
main_inhtest.cpp:24: error: overriding ‘Base<T>::Node** Base<T>::GetNAddr() [with T = int]’
main_inhtest.cpp: In member function ‘Derived<T>::DNode** Derived<T>::GetNAddr() [with T = int]’:
main_inhtest.cpp:57: instantiated from here
main_inhtest.cpp:44: error: invalid static_cast from type ‘Base<int>::Node**’ to type ‘Derived<int>::DNode**’
Could somebody help me understand
Whether this is the right way to be doing this, and if there is a better way, and
Why the compiler is happy with the GetN() methods but not the GetNAddr() methods?
Thanks!
#include <iostream>
#define TRY_GET_N_ADDR 1
template <typename T> class Base {
public:
Base() { n = new Node(); }
struct Node
{
T a;
};
virtual Node *GetN() { return n; }
virtual Node **GetNAddr() { return &n; }
Node *n;
};
template <typename T> class Derived : public Base<T> {
public:
Derived() { Base<T>::n = new DNode(); }
struct DNode : Base<T>::Node
{
T b;
};
// This method is fine
DNode *GetN() { return static_cast<DNode *>(Base<T>::GetN()); }
#if TRY_GET_N_ADDR
// Compiler error here
DNode **GetNAddr() { return static_cast<DNode **>(Base<T>::GetNAddr()); }
#endif
};
int main (int argc, const char * argv[]) {
Derived<int> d;
d.GetN()->a = 1;
d.GetN()->b = 2;
std::cout << d.GetN()->a << " " << d.GetN()->b << std::endl;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题不在于嵌套结构或模板,而在于指向指针的指针和继承:
如果 Base** 可以保存 Derived 数组,您可以执行以下操作:
最后一行将导致一些任意错误。因此,不允许进行此类分配。
The problem is not with nested structs or templates, but with pointers to pointers and inheritance:
If Base** could hold an array of Derived's, you could have done the following:
The last line would have resulted in some arbitrary error. Therefore, that kind of assignment is not allowed.
回答你的第二个问题:
如果你重写虚拟函数,签名必须匹配。此规则的唯一例外是,如果在基类中函数返回对某个类
B
的指针或引用,则重写方法可以返回对类型D
的指针或引用code> 其中D
源自 B(这称为返回类型协方差)。话虽如此,您必须清楚为什么GetN
可以工作 -DNode
派生自Node
并且基类函数返回一个Node *
并且重写器返回DNode*
。现在让我们看看
GetNAddr
。基类方法返回一个Node**
或指向 Node*
的指针。您可以在派生类的重写函数中更改此返回类型如果它要返回从 Node 派生的内容*。但这自然是不可能的,因为指针不能有派生类。DNode*
不是从Node*
派生的 - 因此编译器会抱怨To answer your second question:
If you override a virtual function, the signatures have to match. The only excetion of this rule is that if in the base class the function returns a pointer or a reference to some class
B
, then the overriding method can return pointer or reference to typeD
whereD
is derived from B (this is calles return type covariance). Having said this, it must be clear why yourGetN
works -DNode
is derived fromNode
and the base class function returns aNode*
and the overrider returnsDNode*
.Now let's look at
GetNAddr
. The base class method returns aNode**
orpointer to Node*
. You could change this return type in an overriding function in the derived class if it were to return something that is derived from Node*. But that is naturally impossible, since a pointer cannot have derived classes.DNode*
is not derived fromNode*
- hence the compiler complains