【问题标题】:Mismatch between constructor definition and declaration构造函数定义和声明不匹配
【发布时间】:2009-04-01 15:29:54
【问题描述】:

我有以下 C++ 代码,其中声明中构造函数的参数与构造函数的定义具有不同的常量。

//testClass.hpp
class testClass {
  public:
     testClass(const int *x);
};

//testClass.cpp
testClass::testClass(const int * const x) {}

我能够使用 g++ 编译它而没有警告,这段代码应该编译还是至少给出一些警告?事实证明,64 位 solaris 上的内置 C++ 编译器给了我一个链接器错误,这就是我注意到存在问题的原因。

在这种情况下,匹配参数的规则是什么?这取决于编译器吗?

【问题讨论】:

    标签: c++ g++ solaris


    【解决方案1】:

    在这种情况下,允许从 声明中省略 const 说明符,因为它不会为调用者改变任何内容。

    它只与实现细节的上下文有关。这就是为什么它在定义而不是声明

    例子:

    //Both f and g have the same signature
    void f(int x);
    void g(const int x);
    
    void f(const int x)//this is allowed
    {
    }
    
    void g(const int x)
    {
    }
    

    任何调用 f 的人都不会关心您是否会将其视为 const,因为它是您自己的变量副本。

    与 int * const x 一样,都是你的指针副本。你是否可以指向其他东西对调用者来说并不重要。

    如果您在 const int * const 中省略了第一个 const,那么这会有所不同,因为如果您更改它指向的数据,这对调用者很重要。

    参考:C++ 标准,8.3.5 第 3 段:

    "任何修改 a 的 cv 限定符 参数类型被删除...这样 cv-qualifiers 只影响 参数的定义 函数体;他们不 影响函数类型”

    【讨论】:

    【解决方案2】:

    把它想象成两者之间的相同区别

    //testClass.hpp
    class testClass {
      public:
         testClass(const int x);
    };
    
    //testClass.cpp
    testClass::testClass(int x) {}
    

    这也可以编译。您不能基于按值传递参数的 const-ness 重载。想象一下这种情况:

    void f(int x) { }
    void f(const int x) { } // Can't compile both of these.
    
    int main()
    {
       f(7); // Which gets called?
    }
    

    来自标准:

    不同的参数声明 仅在存在或不存在的情况下 const 和/或 volatile 是等价的。 即 const 和 volatile 每个参数的类型说明符 确定时忽略类型 声明了哪个函数, 定义或调用。 [示例:

    typedef const int cInt;
    int f (int);
    int f (const int); // redeclaration of f(int)
    int f (int) { ... } // definition of f(int)
    int f (cInt) { ... } // error: redefinition of f(int)
    

    —结束示例] 只有 const 和 volatile 类型说明符 参数类型的最外层 规范在此被忽略 时尚; const 和 volatile 埋在 a 中的类型说明符 参数类型规范是 显着,可用于 区分重载函数 声明.112) 特别是, 对于任何类型 T,“指向 T 的指针”, “指向 const T 的指针”和“指向 volatile T”被认为是不同的 参数类型,如“参考 T”、“对 const T 的引用”和 “参考 volatile T。”

    【讨论】:

      【解决方案3】:

      重载解决部分 13.1/3b4 中明确介绍了此示例:

      仅在是否存在 const 和/或 volatile 方面不同的参数声明是 相等的。也就是说,忽略每个参数类型的 const 和 volatile 类型说明符 在确定正在声明、定义或调用哪个函数时。

      [示例:

      typedef const int cInt;
      int f (int);
      int f (const int); // redeclaration of f(int)
      int f (int) { ... } // definition of f(int)
      int f (cInt) { ... } // error: redefinition of f(int)
      

      ——结束示例]

      所以,肯定没问题。

      【讨论】:

        【解决方案4】:

        const int * const xconst int * x 不一样吗,因为你已经做了 const?

        【讨论】:

        • 没有。在第一种情况下,x 是一个指向 const 整数的 const 指针。在第二种情况下,x 是一个 non-const 指针,指向一个 const 整数。
        • 具体来说,首先你既不能修改 x 也不能修改 x。第二种情况,不能修改x,但是可以修改x。例如,第二个可用于遍历数组(例如使用 x++),而第一个则不能。
        猜你喜欢
        • 2022-01-15
        • 1970-01-01
        • 2013-02-03
        • 2016-08-15
        • 1970-01-01
        • 2019-09-18
        • 1970-01-01
        • 2018-06-11
        • 1970-01-01
        相关资源
        最近更新 更多