【问题标题】:C++ Protected / Public overloadsC++ 受保护/公共重载
【发布时间】:2011-09-02 08:51:34
【问题描述】:

我有这样的课:

class Foo
{
public:
    Foo()
    {
        for(int i = 0; i < 10; ++i)
            v.push_back(i);
    };
    const vector<double>& V() const {return v;};
protected:
    vector<double>& V() {return v;};
private:
    vector<double> v;
};

然后是这样的一段代码:

Foo foo;
for(int i = 0; i < (int) foo.V().size(); ++i)
    cout << foo.V().at(i) << endl;

但是,后者引发了一个编译错误,说 V() 调用是一个受保护的方法,而我只是试图从中读取,而不是修改它。

我尝试了以下方法(但没有成功)。

Foo foo;
const vector<double>& test = foo.V();
for(int i = 0; i < (int) test.size(); ++i)
    cout << test.at(i) << endl;

非常感谢您的帮助。

=====

感谢大家的解释和解决方案!非常感谢!

【问题讨论】:

  • 如果你放弃了protected 对它的引用,那么拥有一个private 变量的意义何在? (我个人认为这是邪恶的)。

标签: c++ overloading public protected


【解决方案1】:

不可能对返回值进行重载。当对象是非常量时,将使用非常量方法。可以通过以下方式引导编译器:

const vector<double>& test = const_cast<Foo const&>(foo).V();

或者更好的解决方案是让常量方法具有不同的名称(例如:ConstV)。或者您可以添加这个新方法并将当前方法保留在那里。这种方法用于 C++0x 标准。例如,常量方法 cbegin()cend() 已添加到标准容器中。

【讨论】:

  • 万岁const_cast安全使用
  • 错误答案。 const_cast&lt;Foo const&gt;(foo) 创建一个临时对象,并在该临时对象上调用 V()
  • 您的意思可能是const_cast&lt;Foo const&amp;&gt;(foo)const_cast 需要一个指针或引用)。更好的是使用static_cast
  • @Nawaz,@Luc Danton:谢谢,已更正。但在这种情况下它可能会起作用。临时的只是这样读取的,应该没有问题。
【解决方案2】:

您已接近解决方案。如果 Foo 也是 const,编译器将选择 const 函数。

Foo foo;
const Foo& cfoo = foo; 

for(int i = 0; i < (int) cfoo.V().size(); ++i)
    cout << cfoo.V().at(i) << endl; 

【讨论】:

    【解决方案3】:

    由于foo 不是const,编译器正在尝试使用非常量方法。作为一种解决方法,您可以执行以下操作:

        Foo foo;
        const Foo& cFoo = foo;
        for(int i = 0; i < (int) cFoo.V().size(); ++i)
        cout << cFoo.V().at(i) << endl;
    

    【讨论】:

    • 您可以在for 循环中使用size_t,而不是在(int)cFoo.V().size() 中进行转换。毕竟,at() 接受 size_type 类型的参数,这很可能是 size_t,或 unsigned 整数类型。
    【解决方案4】:

    重载解析不考虑成员的可访问性,因此选择了一个理想的重载候选者,然后检查成员可访问性以查看调用是否合法。

    现实的解决方法是:

    Foo foo;
    Foo const& foo_alias = foo;
    for (std::size_t i = 0; i != foo_alias.V().size(); ++i)
        cout << foo_alias.V().at(i) << endl;
    

    【讨论】:

    • 那么const vector&lt;double&gt;&amp; v = foo.V() 电话不应该没问题吗?只有公共方法返回一个常量向量?谢谢。
    • @foo :不,这意味着您要将返回值绑定到 const&amp; 的事实应该很重要,但重载决议也不考虑函数的返回类型。跨度>
    • @foo:初始化表达式为foo.V();里面没有const。 (拨打电话后,然后会在其上标记const。)
    猜你喜欢
    • 2012-02-13
    • 2023-04-08
    • 1970-01-01
    • 2011-06-19
    • 2013-06-03
    • 2014-03-31
    • 2012-09-09
    • 2011-01-17
    • 2016-03-19
    相关资源
    最近更新 更多