1

我不确定我是否缺少一些基本的东西。但我无法理解为什么编译器会为此代码生成错误:

class A
{
};

class B
{
public:
    B();
    A* get() const;

private:
    A* m_p;
};

B::B()
{
    m_p = new A;
}

A* B::get() const
{
    //This is compiling fine
    return m_p;
}

class C
{
public:
    A* get() const;
private:
    A m_a;
};

A* C::get() const
{
   //Compiler generates an error for this. Why? 
    return &m_a;
}

编辑:编译器错误是:错误 C2440:'return':无法从 'const class A *' 转换为 'class A *' 转换丢失限定符

4

7 回答 7

12

const在函数签名中告诉编译器对象的成员可能不会被修改。然而,您返回一个const指向成员的非指针,从而允许违反该承诺。

在您的班级B中,您没有做出承诺,因为您没有返回指向成员的指针,而是返回了它的副本(并且该成员恰好是指针)。

于 2009-02-09T13:28:58.117 回答
3

这是因为您要从 const 函数返回一个指向成员的非常量指针。

第一部分有效,因为您要返回成员指针的副本,因此这不会违反 get 函数的 const-ness:

class B
{
public:
    B();
    A* get() const;

private:
    A* m_p;
};

A* B::get() const
{
    //This is compiling fine
    return m_p;
}

但是下一位会产生编译错误(在 gcc 4 上)

testfile.cpp:37: 错误:从 'const A*' 到 'A*' 的无效转换</p>

因为您的 const get 函数通过返回指向它的非常量指针来提供对 m_a 的非常量访问。

class C
{
public:
    A* get() const;
private:
    A m_a;
};

A* C::get() const
{
   //Compiler generates an error for this. Why?
    return &m_a;
}
于 2009-02-09T13:28:15.873 回答
1

因为返回的指针不是 const。将其更改为:

class C
{
public:
    const A* get() const;
private:
    A m_a;
};

const A* C::get() const
{
    //Compiler generates an error for this. Why? 
    return &m_a;
}

注意 C::get() 现在返回一个指向 A 的 const 指针。

于 2009-02-09T13:30:25.307 回答
0

标记的成员函数const不能返回非常量引用或指向私有变量的指针。如果编译器允许这样做,您的类之外的任何人都可以修改所述私有变量,并且const函数上的限定符将失去意义。

于 2009-02-09T13:30:26.053 回答
0

这个问题可以用一个更简单的例子来说明:

class MyClass {
public:
    int *get() const;
private:
    int value;
};

int *MyClass::get() const {
    return &value;
}

MyClass::get() constvalue有类型const int。当你取消引用它时,你会得到const int *. 该类型不能安全(隐式)转换为int *. 要纠正您的问题,请get()返回const int *

于 2009-02-09T13:31:11.387 回答
0
A* C::get() const
{
   //Compiler generates an error for this. Why? 
    return &m_a;
}

因为 get() 是一个 const 函数,所以编译器将它引用的所有成员变量都视为 const。当你获取这样一个成员的地址时,你会得到一个指向 const 的指针。但是您的函数正在返回一个非常量指针。您需要将代码更改为

const A* C::get() const
{
    return &m_a;
}
于 2009-02-09T13:33:38.603 回答
0

基本上只是在前面添加一个 const ,

const A* C::get() const
{
   //Compiler generates an error for this. Why? 
    return &m_a;
}

然后如果你想访问它,基本上做:

C something;

const A* a = something.get();

但是,对我来说,您的程序毫无意义。

IMO,这样做最有意义:

class A{
};

class C : public A
{
};

这样你就不必做一个“get”来返回 A 的实例。

于 2009-02-09T16:08:44.847 回答