【问题标题】:One Definition Rule (ODR) when implementing stack in multiple classes在多个类中实现堆栈时的一个定义规则 (ODR)
【发布时间】:2015-05-28 09:10:48
【问题描述】:

似乎无法让简单的堆栈实现工作。我只是想让两个不同的类(B 类和 C 类)能够在由第三类(A 类)管理的 same 堆栈中推送和打印元素。

A.cpp

#include "A.h"
void A::pop() {}
void A::push() {}
void A::print() {}  // prints last pushed elements

啊.h

#include < iostream >
  class A 
  {
    public:
    void pop();
    void push();
    void print();
  }

B.cpp

#include "B.h"
#include "A.h"

A a;

void B::Text() { a.push(); }
void B::Background() { a.print(); }  // works!

C.cpp

#include "C.h"
#include "A.h"

A _a; // why doesn't A a work? because ODR?
void B::Text() { _a.push(); }
void B::Background() { _a.print(); } // doesn't work! breakpoint shows empty stack!

我认为我违反了单一定义规则。我说的对吗?

【问题讨论】:

  • 如果在 C.pp 中我将 A 类定义为“A a”而不是“A _a”,则不会。其次,您知道为什么当我尝试访问 B 类中的堆栈时它是空的,即使我只是在该类中推送了一个元素。
  • 你基本上是在谈论一个全局变量。所有常见的警告都适用(总结:不要这样做!!)。但是如果你只是必须这样做,那么决定哪个cpp文件应该是a的规范“所有者”,在那里定义它,然后将extern A a放在头文件中。
  • @Daqs 只是为了准确:我已将 A 类定义为“A a” — 您已定义了一个 a 类的 对象 987654328@.
  • @Melebius 明白了!谢谢
  • @bolov:考虑到许多违反 ODR 的行为不需要被诊断出来,这是一个大胆的声明……例如 a.cpp:inline int f() { return 1; } 和 b.cpp:inline int f() { return 2; };将两者链接在一起违反了 ODR,但您的链接器可能无法诊断它们。

标签: c++ stack one-definition-rule


【解决方案1】:

是的,每个变量必须只定义一次。 在 C.cpp 中使用 extern A a

【讨论】:

  • 这解决了问题。在 B 类中,我将 A a 声明为 extern,并且我能够在 C 类中毫无问题地访问堆栈。谢谢!我会尽快选择这个作为答案。
  • @Daqs 不过那是个糟糕的设计。您不应该依赖全局变量。
  • @juanchopanza 为什么不呢?来个建设性的批评如何?
  • @Daqs 看看吧。想想如果你依赖可以在任何地方修改的东西会发生什么。
  • @juanchopanza 好的,我会的。谢谢!
【解决方案2】:

通过在 B.cpp 中创建 A a 和在 C.cpp 中创建 A a,您实际上有 2 个不同的对象,它们不会指向同一个堆栈。

实现相同目标的另一种方法是将A 设为单例对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2015-08-07
    • 2021-12-21
    • 1970-01-01
    • 2022-08-02
    • 1970-01-01
    • 2012-01-01
    相关资源
    最近更新 更多