2010-09-21 13 views
1

我想知道使用非虚拟派生什么时,由编译器产生的:非虚拟派生:我真的从编译器中得到什么?

template< unsigned int D > 
class Point 
{ 
    int[D]; 
    // No virtual function 
    // ... 
}; 
class Point2 : public Point<2> {}; 
class Point3 : public Point<3> {}; 

这里并推导只意味着编译时检查?还是有一些其他开销?

我注意到,当使用Point2或直接使用Point<2>时,我的编译器会生成相同大小的对象。我推断派生没有产生一个虚拟表,因此,永远不会进行虚拟呼叫。

我错过了什么吗?


语境

我想提供一对夫妇给定类模板的预定义的特化。我开始用的typedef:

template< unsigned int D > 
class Point 
{ 
    int[D]; 
}; 
typedef Point<2> Point2; 
typedef Point<3> Point3; 

唉,这可以防止客户端使用“简单”的前置声明:

// No #include <Point.h> 
class Point2; // 'Point2': redefinition; different basic types 
class Point3; // 'Point3': redefinition; different basic types 

它是那么必须写这个相当直观的代码:

// No #include <Point.h> 
template< unsigned int > class Point; 
typedef Point<2> Point2; 
typedef Point<3> Point3; 

这就是为什么我放弃了typedefs并使用了非虚拟派生。不过,我想知道的全部是什么意思。

(另一种策略是在一个专用的头文件编写一次向前声明,点菜#include <iosfwd>

+1

对不起,但typedefs有什么问题? – ybungalobill 2010-09-21 15:52:49

+0

我无法转发 - 声明类模板的typedef。例如,我不能转发声明'class ostream',我必须'#include '而不是 - 请参阅http://www.gotw.ca/gotw/034.htm – 2010-09-21 16:09:09

+1

从这篇文章中,您必须使用''是正确地转发声明它将不得不在std命名空间中完成,这对您不合法。我看不出为什么你不能转发declare Point并在专用头文件中使用这些typedefs。 – UncleBens 2010-09-21 17:27:03

回答

1

好吧,看起来像没有人迄今已给你一个实际的回答你的问题:

没有,没有开销,非虚拟派生。 编译器不必创建一个vtable,没有虚函数调用,一切都很好。 它通常是通过在派生类的开头放置一个基类的实例来实现的,这样指向派生类的指针也可以作为指向基类的指针。然后一切只是工作

当然,构造函数调用必须被转发,但它们通常会被内联,也消除了这种开销。但是,如果您使用多个基类,它可能会引入一小部分开销(取决于编译器如何实现它)。可能不多(this指针必须随时调整),但理论上,它在那里。

0

我实在不明白的问题,这里采用的是使用类型定义是什么。这是typedef的目的之一。我相信在命名空间中工作时有一些限制,但在这里看起来并不像你正在做的那样。这是我们经常见到这样的事情:

general.h中

#include <map> 
#include <string> 

class MyObj1; 
class MyObj2; 

typedef map< string, MyObj1 > MyObj1Map; 
typedef map< string, MyObj2 > MyObj2Map; 

然后,您可以在您的源代码,但你必须记住要包括MyObj1MyObj2定义编译器将需要知道大小(即,除了声明中的引用和指针外)。

+0

@Julien L .:刚刚听到您的评论,您正在尝试转发 - 声明类模板的typedef,因此上述可能性不适用。道歉。 – 2010-09-21 16:20:48

0

由于以下原因,我总是使用前向声明(typedef):

  1. 继承是generics的替代方案。
+1

对不起,但我不知道你想说什么。 – sbi 2010-09-21 18:36:23

+0

编辑。我还没有看到你最后的评论。 – yadab 2010-09-21 18:54:32

+0

我不问你是喜欢typedefs还是派生,我在问什么是派生的开销(当没有虚函数的时候) - 谢谢 – 2010-09-22 07:46:38

0

继承问题是您必须重新定义构造函数。

标准溶液(我不明白为什么你不希望它)是一个专门的标题:

// File PointFwd.h 
#ifndef POINT_FWD_H 
#define POINT_FWD_H 1 

template <unsigned> class Point; 

typedef Point<2> Point2; 
typedef Point<3> Point3; 

#endif 

您的客户只需要包括"PointFwd.h"转发声明他们想要的东西。

+0

这不是我的问题 – 2010-09-28 12:20:03

+0

@Julien:“我错过了什么吗?” =>“继承的问题是你必须重新定义构造函数”。 – 2010-09-28 12:34:10

相关问题