C++ 应该";常数;在语义上或语法上使用? A类 { ... 公众: 共享_ptr GimmeLogger()常量 { 返回m_记录器; } 私人: 共享_ptr m_记录器; };

C++ 应该";常数;在语义上或语法上使用? A类 { ... 公众: 共享_ptr GimmeLogger()常量 { 返回m_记录器; } 私人: 共享_ptr m_记录器; };,c++,constants,C++,Constants,在A类中,GimmeLogger应该是const还是非const? 如果是const,这是有意义的,因为它是一个简单的getter,不会修改*这个(语法const) 但另一方面,它返回一个非常量指针,指向它所拥有的另一个对象(语义上为非常量)。如果您使用该非常量,则无法写入: class A { ... public: shared_ptr<Logger> GimmeLogger () const { retu

A类
中,
GimmeLogger
应该是
const
还是非
const

如果是
const
,这是有意义的,因为它是一个简单的getter,不会修改
*这个
(语法
const


但另一方面,它返回一个非常量指针,指向它所拥有的另一个对象(语义上为非常量)。

如果您使用该非常量,则无法写入:

class A
{
    ...

    public:
        shared_ptr<Logger> GimmeLogger () const
        {
            return m_logger;
        }

    private:
        shared_ptr<Logger> m_logger;
};
所以如果你想写这个;也就是说,如果您想在const对象上调用
GimmeLogger
,那么将
GimmeLogger
设置为const成员函数,因为您无法在const对象上调用非const成员函数。但是,您可以在非常量对象(以及常量对象)上调用常量成员函数


在常量成员函数中,每个成员在语义上都是常量对象。因此,函数中的
m_logger
类型变为
const share_ptr
。因此,相应地更改返回类型。

是的,它应该是
const
。函数的
常数
-与返回类型的
常数
-无关


我明白你的意思,但我认为函数仍然是
const

因为
const
是一个关键字,它在语法上被检查,但它应该在语义上被使用,也就是说,在你的设计操作中,不改变你的类的可见状态的函数应该被标记为
const

这就是
mutable
关键字背后的全部思想:添加标记成员的功能,因为这不参与对象的可见状态,因此语法检查与语义匹配。在您的特定情况下,因为您正在复制指针,所以您甚至不需要在那里使用
mutable
(这实际上是常量正确性的弱点之一,因为返回非常量指针不会在编译时触发错误,即使您正在为对象中的更改打开一扇门)


另一方面,在这个特殊的例子中,我看不出有什么好的理由让对象公开它的日志。。。也就是说,撇开常量正确性不谈,为什么需要授予对记录器的访问权限?

通常,如果可以避免,就不应该返回成员数据的句柄。努力回顾你的设计并找到解决方法。也就是说,如果必须,它应该是
const
。这允许您对
const
对象以及非const对象调用函数。请参见示例
std::string::c_str()
。您还可以重载该函数,以便同时获得这两个函数,就像标准容器对迭代器所做的那样


如果有疑问,请在标准库中查找提示。

是否可以将
m_logger
改为
shared_ptr
?Scott Mayer的书(有效C++)第21项对
const
进行了有趣的讨论。如果你正在编程C++,这是一本很值得阅读的书。基本上,结果是在可能的情况下使用
const
,并使用摇摆室。您是特别询问伐木者,还是一般的“拥有”对象?从功能编程的角度来看,单子的概念不太深入,你可能认为一个记录器是在没有真正改变其状态的情况下被抛出的数据。因此,你没有理由不使用属于const object的记录器。呃…“第一方当事人在本合同中应被称为第一方当事人。”——摘自《歌剧之夜》
void f(const A & a)
{
    auto v = a.GimmeLogger(); //error
}