2015-04-20 39 views
0

在示例代码中,调用message()将永远不会影响类的内容,所以我希望该方法为const。但我不希望返回值也为const,那么使用const_cast如下安全吗?还是有更好的解决方案?这是const_cast的有效用法吗?

编辑:对不起。所以n_是一个指针!

编辑2:我终于设法正确地重新产生问题。如果n_是一个数组,如int n[100]?然后,我确实看到没有const_cast的问题。

class A 
{ 
private: 
    int n_[10]; 

public: 
    /* ... */ 

    int* n() const 
    { 
     return const_cast<int*>(n_); 
    } 
}; 
+4

是的,但没有必要。你没有返回一个引用,所以调用者无法通过调用'n()'来修改'n_'。 – jxh

+1

当前的代码试图返回一个'int *'作为'int'。 –

+0

现在你允许我这样做:'const A a; int * p = a.n(); p [0] = 2;'。所以不,它根本就不安全。 – chris

回答

5

不,这不是const_cast的有效用途。

你的函数没有修改数组,但它正在授予修改数组给调用者的权限。因此,它本身应该拥有这些权利。你不能让某人访问你自己无法访问的内容。所以这个方法不应该是const的,并且const转换是不必要的。

您可能还需要该函数的const版本,该函数返回const int*。这与原理相同,例如,std::vector::operator[]。即使运算符没有修改向量,但它授予访问权限来修改向量,因此它不是const函数。 (但也有一个常量重载版本,它返回一个const引用,因此不授予修改向量的权利)

7

返回一个类型(而不是引用)将使复制你返回对象的。因此不需要施放它,副本可以在不影响原始的情况下进行更改。如果您删除了const_cast,代码将会干净地编译。

编辑:基于最新编辑的问题,我会说这是一个滥用const_cast。 C++遵循的原则是const成员函数不仅不应该对对象本身做任何更改,而且不应该返回任何可用于在函数外进行更改的内容。通过返回一个非const指针给成员变量,你违反了这个原则。

+0

在该函数的上下文中,不是'n_'隐式'const'? – tadman

+0

你能看到我的编辑?我在原帖中犯了一个很大的错误。 – xiver77

+0

@tadman是的,但你可以毫无困难地创建一个'const'变量的副本。 –

0

你可以只返回n_,因为它是

int n() const 
{ 
    return n_; 
} 
0

没有必要使用石膏。在该函数中,this->n_是一个const指针,它不指向const int

int* n() const 
{ 
    // No need for a cast. 
    return n_; 
} 

它更有意义,从const函数返回一个const int*。你不希望这样的事情:

const A a; 
a.n()[0] = 10; 

这颠覆了const -ness的对象。您可以通过使用以下方法来防止这种情况:

const int* n() const 
{ 
    // No need for a cast either. 
    return n_; 
} 
0

一般而言,将T const转换为Tconst_cast<>几乎总是不必要的。这是因为常量对象正在转换为非常量临时对象,并且这可以在没有强制转换的情况下安全地完成。

int const n; // n is a constant int 
int x = n;  // perfectly safe 

即使T是指针类型也是如此。

int * const n; // n is a constant pointer to an int 
int * x = n; // perfectly safe 

但是,如果移动const关键字前,它不再是使得指针类型不变,但被指向到常量的类型。因此,我们上面的例子:

const int * n; // n is a pointer to a constant int 
int * x = n // error, x is a pointer to an int 

你可以看到,x点,比n点不同的东西,所以初始化失败。在这种情况下,初始化将需要const_cast<>

int * x = const_cast<int *>(n); 
       // cast away the const-ness that n is pointing to 

你只能这样做,如果你知道n实际上是modifyable(它可能不是如果指针是实际只读存储器),或者如果您知道x的用户实际上不会尝试修改n指向的内容。


对于你的榜样,你似乎认为你const方法应该返回一个指针,以这样一种方式,该数据是由调用者修改你的对象保存数据。也就是说,由于n()方法被声明为const,这意味着被访问对象的内容应该被视为常量。因此,n_是一个常数为int的数组,它将衰减为指向常量int的指针,但您要返回指向int的指针。

如果您打算n_是可修改的,无论该对象是否被视为常量,您可以使用mutable声明该意图。这将使n_被视为非常量,即使包含对象是const,并且它因此使const_cast不必要。

class A 
{ 
private: 
    mutable int n_[10]; 

public: 
    /* ... */ 

    int* n() const 
    { 
     return n_; 
    } 
};