【问题标题】:operator declaration within namespace in a header?标题中命名空间内的运算符声明?
【发布时间】:2012-01-01 15:29:26
【问题描述】:

请原谅,但我不知道简短地给标题命名。

为什么我需要在头文件中声明一个重载的操作符才能使它在这个例子中工作:

头.H

#pragma once

namespace test {
    class A {
    public:
        A() : x(0) {}
        int x;
    };
    A& operator++(A& obj);  //this is my question
}

HEAD.CPP

#include "head.h"

namespace test {
    A& operator++(A& obj) {
        ++obj.x;
        return obj;
    }
}

MAIN.CPP

#include <iostream>
#include "head.h"
using namespace std;
using namespace test;

int main() {
    A object;
    ++object;  //this won't work if we delete declaration in a header
    return 0;
}

operator++ 是在“head.cpp”内的命名空间中定义和声明的,那么为什么我需要在标题中再声明一次呢? 谢谢。

【问题讨论】:

  • 为什么不在你的类中声明操作符??
  • @Alex :在课堂之外定义非赋值运算符通常被认为是一种好习惯。但是,运算符可以在标题内定义inline...
  • @Alex 我在这个例子的类 cos 之外定义了它,我目前正在努力解决这个问题,它可能是任何其他函数的同一个问题。谢谢。
  • 刚刚在这里找到了一个很好的答案:stackoverflow.com/questions/4652932/… :)

标签: c++ namespaces operator-keyword


【解决方案1】:

CPP 文件是相互独立编译的,它们只能看到它们包含的头文件(实际上是在编译之前以文本形式添加到 CPP 的源代码中)。因此,您将使用头文件通知编译器存在具有该签名的函数(无论是运算符重载)。

然后,您的 CPP 文件的输出由链接器组合在一起,此时您会发现,例如,您是否在头文件中声明了一个函数,但从未费心实现它。

带有命名空间的简单示例:

#include <iostream>

namespace test{
    int f() { return 42; }
    int g() { return -1; }
}

namespace other{
    int f() { return 1024; }
}

using namespace other;

int main(){

    //error: 'g' was not declared in this scope
    //std::cout << g() << std::endl;

    std::cout << test::f() << std::endl; //42
    std::cout << f() << std::endl; //1024

    return 0;
}

【讨论】:

  • 是的,在编译期间 head.cpp 对 main.cpp 没有影响,他们只是看不到对方。例如,尝试删除 head.cpp 中的运算符,但将声明保留在 head.h 中。 main.cpp 仍然可以正常编译。 (编译后链接阶段会有错误。)这是C++编译模型的结果。
  • 我知道我听起来很笨,但我只是不明白这一点,我已经通过“使用命名空间测试”将命名空间中的所有内容都包含在“MAIN.CPP”中,因此运算符函数已定义且可见,以及为什么那它不起作用吗? header 只是一个声明。
  • 遗憾的是,这不是 C++ 命名空间的工作方式。有关快速介绍,请参阅here。本质上,它们是关于对事物进行逻辑分组并消除命名冲突。除其他外,using namespace std 允许您使用 cout &lt;&lt; ... 而不是 std::cout &lt;&lt; ...,但这并不意味着您不必包含 &lt;iostream&gt;
  • 当你编译 main.cpp 时,编译器不会看到 head.cpp 里面有什么。 “使用命名空间测试”不会引入任何在 head.cpp 中声明的东西,它只会进行命名空间测试并使命名空间测试中的每个符号也可用,而无需在命名空间之前显式地使用它;在“使用命名空间测试”之后你不需要写test::A,你可以写A。
  • 好的!我现在明白了,我认为命名空间与标题具有相似的行为。(我很傻)非常感谢大家。
猜你喜欢
  • 2017-11-28
  • 1970-01-01
  • 1970-01-01
  • 2015-03-29
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 2015-11-25
  • 1970-01-01
相关资源
最近更新 更多