从标头中的类实例化对象

时间:2013-12-22 19:25:50

标签: c++ header-files instantiation

我遇到multiple defintion of Math错误而没有来自以下代码的原因文件:

#ifndef SOMEMATH_H
#define SOMEMATH_H

class math{
public:
    int add( int a, int b);
    int divide(int a, int b);
    int subtract(int a, int b);
    int multiply( int a, int b);
}Math;

#endif // SOMEMATH_H

Math更改为任何其他名称不会改变问题。以不同方式实例化数学对象不能解决问题。不在头文件中创建math的对象不会导致任何问题,但我想在标头中创建一个类。这可能吗?

3 个答案:

答案 0 :(得分:2)

简短回答:标题中没有实例化。

答案很长:您的文件直接或间接包含在其中的每个cpp都有一个对象Math,链接器会抱怨,因为它不能只选择一个。

关于这个主题的更多内容,http://csapp.cs.cmu.edu/public/ch7-preview.pdf涵盖了unix链接器,但这个想法将保持不变。基本上你的例子失败了:

  

规则1:不允许使用多个强符号

说实话,我认为(但不确定)在大多数情况下,链接器可以决定在大多数情况下创建对符号的引用,并将“.o”中的一个作为真实内容宾语。但只有1个库,因此一旦你有多个DLL,bug就会上升。所以这不值得痛苦。

所以一般规则是“头部没有实例化”。如果你想要一个全局变量:

  • 在一个cpp中实例化math Math(如果需要,甚至是专用的)。
  • 在使用它的其他文件中使用“extern math Math”。

但如果可以,请避免使用全局对象。

答案 1 :(得分:2)

您的标头定义了class math名为Math的实例,这是一个坏主意,因为它会导致您遇到的问题:如果两个文件包含标题,则会获得两个实例一样的名字。

您无法在此标头中安全地创建类的实例。您可以声明存在的那个,并将实际的定义放在.cpp源文件中。

这个特殊的类看起来只有方法,没有与之关联的实际数据。这让我想知道你真正想要做什么。如果您只是在一个名称下捆绑一组函数,则可以考虑使用namespace,或者至少在类下面设置函数static

class Math {
public:
    static int add( int a, int b);
    static int divide(int a, int b);
    static int subtract(int a, int b);
    static int multiply( int a, int b);
};

或:

namespace Math
{
    int add( int a, int b);
    int divide(int a, int b);
    int subtract(int a, int b);
    int multiply( int a, int b);
}

这些选项中的任何一个都将使您无需使用类的实例来访问该功能。您可以将这些功能称为Math::add()Math::divide()

答案 2 :(得分:1)

// .hpp
#ifndef SOMEMATH_H
#define SOMEMATH_H

class math{
public:
    int add( int a, int b);
    int divide(int a, int b);
    int subtract(int a, int b);
    int multiply( int a, int b);
};

extern math Math;

#endif // SOMEMATH_H

// .cpp

math Math;

但看起来你正试图模仿Java的Math类。只需使用命名空间。