编程菜鸟,在学习c++多态性的过程中,写了这样的测试代码,这里会有类型限定符不兼容。
当我在抽象基类的函数声明后添加上const后,就不会出现类型不兼容,这是为什么?
PHP中文网2017-04-17 13:22:14
Const-qualified variables and their references can only call const-qualified member functions
Const-qualified means that the value of the variable will not change. If you want to not change the value of the variable, you can only call const-modified member functions
高洛峰2017-04-17 13:22:14
Your question actually has nothing to do with polymorphism. To answer your question, two aspects of knowledge are needed.
this
pointerFirst of all, to access the members of the class within the member function of the class, you need to access it through the this
pointer (it can be omitted if the name does not conflict). When calling a member function through an object, the object itself will be passed through the this
pointer Passed to member function. For example:
class A {
public:
explicit A(int xx = 0) : x(xx) {}
int get() { return x; }
void set(int xx) { x = xx; }
private:
int x;
};
int main() {
A a;
a.set(10); // a.x = 10
int i = a.get(); // i = 10
}
Why can I access the member a.get()
of object a
in the x
function? Just through this this
pointer. When calling a
through a.get()
, the compiler will assign the address of object a
to the this
pointer, where the type of the this
pointer is A *const
. Within the get()
function, the statement return x;
is actually equivalent to return this->x;
, so we can access the member a.get()
of the object a
through x
.
Similarly, why can a.set(10);
assign the value of member a
of object x
to 10? Also through the this
pointer. x = xx;
is equivalent to this->x = xx;
.
In the above two cases, since there is no ambiguity in the parsing of x
, the this
pointer can be omitted. However, what if I want to use the same variable name as the member set
in the parameters of the member function x
? Still distinguished by the this
pointer. We can modify the definition of member function set
as follows:
A::void set(int x) { this->x = x; }
The this
pointer here cannot be omitted, otherwise, there will be ambiguity when written as x = x;
, and the compiler cannot resolve whether x
is a parameter of a function or a member of an object.
const
Member functionsConsider a situation. In the previous example, our object a
is a non-constant object. What if we want to use class A
to declare a constant object? For example
int main() {
const int ci = 10;
int i = ci;
const A ca(5); // ca.x = 5
int j = ca.get(); // 编译错误
}
For built-in types, you can directly define a constant ci
and use its value. For our own defined class A
, we can also use the same method to define constants ca
and obtain the value of member ca.get()
of object a
through x
.
However, when using member functions to obtain the value of its data member x
, we actually still access the member this
through the x
pointer. The problem is that at this time, the this
pointer is not const A *const
type, but A *const
type. We know that the content of a constant cannot be accessed through a non-const pointer, that is,
const int ci = 5;
int *p = &ci; // 错误
const int *cp = &ci; // 正确
So how to access member this
through x
pointer? We need to find a way to make the this
pointer into a const A *const
type. The way is to add the const
keyword at the end of the class member function declaration, which means that the member function is
const
member function, and the this
pointer within the function is a constant type. For example, we can overload the get()
method:
int A::get() const { return x; }
At this time,
int j = ca.get(); // j = 5
It will run normally.
Specific to your question,
When I add
const
after the function declaration of the abstract base class, there will be no type incompatibility. Why is this?
In the store_file()
function, its parameter img_file
is a constant reference type. If you want to call a member function through a constant object, you need the this
pointer of the member function of this object to also be a constant type.
When you add get_file_name()
after the const
function declaration of the abstract base class, the this
pointer in this function changes from the Image_file *const
type to the const Image_file *const
type. At this time, return file_name + std::string(".gif");
The member file_name
in is called through the this
pointer of constant type. Thus the above requirements are met.