C++ - 方法和重载中的 const 关键字
C++ - const keyword in methods and overload
为什么这个程序:
#include <iostream>
using namespace std;
class Base {
public:
Base() { cout << "Costruttore Base" << endl; }
virtual void foo(int) { cout << "Base::foo(int)" << endl; }
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
virtual void bar(double) { cout << "Base::bar(double)" << endl; }
virtual ~Base() { cout << "Distruttore Base" << endl; }
};
class Derived : public Base {
public:
Derived() { cout << "Costruttore Derived" << endl; }
void foo(int) { cout << "Derived::foo(int)" << endl; }
void bar(int) const { cout << "Derived::bar(int)" << endl; }
void bar(double) const { cout << "Derived::bar(double) const" << endl; }
~Derived() { cout << "Distruttore Derived" << endl; }
};
int main() {
Derived derived;
Base base;
Base& base_ref = base;
Base* base_ptr = &derived;
Derived* derived_ptr = &derived;
cout << "=== 1 ===" << endl;
base_ptr->foo(12.0);
base_ref.foo(7);
base_ptr->bar(1.0);
derived_ptr->bar(1.0);
derived.bar(2);
return 0;
}
在调用base_ptr->bar(1.0);
中调用Base::bar(double)
,而不是在derived_ptr->bar(1.0);
中调用Derived::bar(double) const
。
我知道那是关于 const
关键字的,但我不明白为什么编译器会选择不同的重载函数。
如果我删除 const
关键字,一切都会按预期工作,在这两种情况下都会调用 Derived::bar
那是因为const
改变了函数的签名,所以它们是不同的。要么同时创建基础 class 和派生 class const
,要么不创建,否则一个不会覆盖另一个。
这是因为您并没有真正覆盖函数 bar()。您正在派生的 class 中使用不同的签名定义 new 函数 bar()。
所以要么删除派生class中的const,要么在上class中的bar()的签名中添加一个const。 (或者保持原样,但要知道您现在在派生 class 中有两个名为 bar() 的函数,其中一个是隐藏的)
C++11 添加了 override
specifier 以防止此类 意外 。使用 override
关键字,编译器只会编译您的代码,如果它覆盖了。
假设 覆盖 bar(int)
的 (这也适用于 bar(double)
:
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This isn't an override, program is well formed
void bar(int) const { cout << "Derived::bar(int)" << endl; }
};
Derived
中的 bar
成员函数没有覆盖基 class 自己的。由于 const
限定条件不同,因此成员函数签名不同。 您在派生 class 中所做的只是添加一个新的重载并隐藏基 class'.
的重载
在派生的 class 中添加 override
关键字,如果它没有覆盖,编译器将给出诊断。
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This isn't an override, program is ill-formed, diagnostic required
void bar(int) const override { cout << "Derived::bar(int)" << endl; }
};
要覆盖,成员函数签名必须相同。
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This overrides
void bar(int) override { cout << "Derived::bar(int)" << endl; }
};
所以,只要你想覆盖,就学会使用 override 关键字,它会让你省去一些麻烦。
为什么这个程序:
#include <iostream>
using namespace std;
class Base {
public:
Base() { cout << "Costruttore Base" << endl; }
virtual void foo(int) { cout << "Base::foo(int)" << endl; }
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
virtual void bar(double) { cout << "Base::bar(double)" << endl; }
virtual ~Base() { cout << "Distruttore Base" << endl; }
};
class Derived : public Base {
public:
Derived() { cout << "Costruttore Derived" << endl; }
void foo(int) { cout << "Derived::foo(int)" << endl; }
void bar(int) const { cout << "Derived::bar(int)" << endl; }
void bar(double) const { cout << "Derived::bar(double) const" << endl; }
~Derived() { cout << "Distruttore Derived" << endl; }
};
int main() {
Derived derived;
Base base;
Base& base_ref = base;
Base* base_ptr = &derived;
Derived* derived_ptr = &derived;
cout << "=== 1 ===" << endl;
base_ptr->foo(12.0);
base_ref.foo(7);
base_ptr->bar(1.0);
derived_ptr->bar(1.0);
derived.bar(2);
return 0;
}
在调用base_ptr->bar(1.0);
中调用Base::bar(double)
,而不是在derived_ptr->bar(1.0);
中调用Derived::bar(double) const
。
我知道那是关于 const
关键字的,但我不明白为什么编译器会选择不同的重载函数。
如果我删除 const
关键字,一切都会按预期工作,在这两种情况下都会调用 Derived::bar
那是因为const
改变了函数的签名,所以它们是不同的。要么同时创建基础 class 和派生 class const
,要么不创建,否则一个不会覆盖另一个。
这是因为您并没有真正覆盖函数 bar()。您正在派生的 class 中使用不同的签名定义 new 函数 bar()。
所以要么删除派生class中的const,要么在上class中的bar()的签名中添加一个const。 (或者保持原样,但要知道您现在在派生 class 中有两个名为 bar() 的函数,其中一个是隐藏的)
C++11 添加了 override
specifier 以防止此类 意外 。使用 override
关键字,编译器只会编译您的代码,如果它覆盖了。
假设 覆盖 bar(int)
的 (这也适用于 bar(double)
:
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This isn't an override, program is well formed
void bar(int) const { cout << "Derived::bar(int)" << endl; }
};
Derived
中的 bar
成员函数没有覆盖基 class 自己的。由于 const
限定条件不同,因此成员函数签名不同。 您在派生 class 中所做的只是添加一个新的重载并隐藏基 class'.
在派生的 class 中添加 override
关键字,如果它没有覆盖,编译器将给出诊断。
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This isn't an override, program is ill-formed, diagnostic required
void bar(int) const override { cout << "Derived::bar(int)" << endl; }
};
要覆盖,成员函数签名必须相同。
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This overrides
void bar(int) override { cout << "Derived::bar(int)" << endl; }
};
所以,只要你想覆盖,就学会使用 override 关键字,它会让你省去一些麻烦。