为什么内联我的访问器会破坏我的代码?

时间:2015-11-25 16:27:25

标签: c++ visual-studio-2012 inline header-files member-functions

我遇到一个奇怪的问题,试图inline我的“Person”类的访问器导致代码无法编译。

以下代码将成功编译并运行(使用Visual Studio 2012):

Person.h

#pragma once
#include <string>

using namespace std;

class Person
{
public:
    Person(string name, int age = 0);
    ~Person(void);

    // Accessors
    string name(void) const;
    int    age (void) const;

private:
    string m_name;
    int    m_age;
};

Person.cpp

#include "stdafx.h"
#include "Person.h"


Person::Person(string name, int age) :
    m_name(name),
    m_age (age )
{}


Person::~Person(void) {}

string Person::name(void) const
{
    return m_name;
}

int Person::age(void) const
{
    return m_age;
}

header_test.cpp

#include "stdafx.h"
#include <iostream>
#include "Person.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    Person p("Joe");

    cout << p.name() << endl;

    return 0;
}

如果我将访问者更改为 inline ,则代码会中断。

在Person.h中内联访问者

// Accessors
inline string name(void) const;
inline int    age (void) const;

在Person.cpp

中内联访问者
inline string Person::name(void) const
{
    return m_name;
}

inline int Person::age(void) const
{
    return m_age;
}

执行此操作会产生以下错误:

  

1&gt; header_test.obj:错误LNK2019:未解析的外部符号“public:class std :: basic_string,class std :: allocator&gt; __thiscall Person :: name(void)const”(?name @ Person @@ QBE? AV?$ basic_string @ DU?$ char_traits @ D @ std @@ V?$ allocator @ D @ 2 @@ std @@ XZ)在函数_wmain中引用

     

1&gt;致命错误LNK1120:1个未解析的外部

上帝,错误信息是神秘的...感谢所有这些哦有用的信息Microsoft / Visual Studio!

我知道inline关键字只是编译器的“提示”,可能在这里没有实际价值,但它仍然不应该破坏代码!

为什么会这样?

2 个答案:

答案 0 :(得分:3)

我不是语言律师,所以我无法判断编译器的行为是否合法。然而,我可以解释正在发生的事情。

当您标记函数inline时,您暗示编译器可以内联此函数。由于超过10年,编译器不需要您的提示。他们知道什么时候内联。相反,你做了什么,你表明函数定义对于它所包含的每个翻译单元都是本地的。对于这个定义应该是可用的。

有效地说,name()定义应该是每个.cpp文件的本地定义,但是您并没有为每个.cpp文件提供这个定义!我仍然认为编译器可以在此发出警告。

答案 1 :(得分:1)

如果要使用inline关键字,则需要在标题中定义函数体。 inline也不只是给编译器一个提示:它或多或少地关闭了&#34;一个定义&#34;规则*关于函数被定义一次且仅一次。

此外,如果在头文件中定义类成员函数,则ala

class Foo {
    int bar() { return 5; }
};
他们得到了#34;内联&#34;默认情况下,没有理由输入关键字: - )

*技术上没有,但为了简单起见,您可以将其视为行为方式。请参阅SergeyA的以下评论。