2022成都解封倒计时,网站seo招聘,阿里云有域名之后怎么建设网站,计算机哪个专业最吃香女生const与取地址重载 前言一、const正常用法const成员函数问题const对象可以调用非const成员函数吗非const对象可以调用const成员函数吗const成员函数内可以调用其它的非const成员函数吗非const成员函数内可以调用其它的const成员函数吗总结 二、取地址及const取地址操作符重载概… const与取地址重载 前言一、const正常用法const成员函数问题const对象可以调用非const成员函数吗非const对象可以调用const成员函数吗const成员函数内可以调用其它的非const成员函数吗非const成员函数内可以调用其它的const成员函数吗总结 二、取地址及const取地址操作符重载概念示例 前言
类的6个默认成员函数如果一个类中什么成员都没有简称为空类。
空类中真的什么都没有吗并不是任何类在什么都不写时编译器会自动生成以下6个默认成员函数。
默认成员函数用户没有显式实现编译器会生成的成员函数称为默认成员函数。
class Date {};一、const
正常用法
在C中可以使用const关键字来声明一个常量成员。常量成员是指在类中声明的成员变量被标记为只读即不能在类的方法中进行修改。常量成员的值在对象创建时被初始化并且在对象的整个生命周期中保持不变。
常量成员的声明方式为在成员变量的类型前加上const关键字。例如
class MyClass {
public:const int myConst 10; // 常量成员的声明和初始化
};在上述示例中myConst被声明为一个常量成员其初始值为10。
const成员函数
除了上面的这种用法外C在类里定义了新的const用法将const修饰的“成员函数”称之为const成员函数const修饰类成员函数实际修饰该成员函数隐含的this指针表明在该成员函数中不能对类的任何成员进行修改。 我们来看看下面的代码
class Date
{
public:Date(int year, int month, int day){_year year;_month month;_day day;}void Print(){cout Print() endl;cout year: _year endl;cout month: _month endl;cout day: _day endl endl;}void Print() const{cout Print()const endl;cout year: _year endl;cout month: _month endl;cout day: _day endl endl;}
private:int _year; // 年int _month; // 月int _day; // 日
};
void Test()
{Date d1(2022, 1, 13);d1.Print();const Date d2(2022, 1, 13);d2.Print();
}问题
请思考下面的几个问题
const对象可以调用非const成员函数吗
不可以。在C中一个对象如果被声明为const则表示该对象是只读的其成员变量不能被修改。因此一个const对象只能调用其成员函数中被声明为const的成员函数。
如果一个成员函数没有被声明为const则它默认是一个非const成员函数。非const成员函数可以修改对象的成员变量因此不能被const对象调用。
如果一个成员函数需要被const对象调用应该在函数声明的末尾加上const关键字。这样声明的成员函数被称为const成员函数它保证不修改对象状态并且可以被const对象调用。
示例
class MyClass {
public:void nonConstFunc() {// 可以修改对象状态的非const成员函数}void constFunc() const {// 不能修改对象状态的const成员函数}
};int main() {const MyClass obj;obj.constFunc(); // 可以调用const成员函数// obj.nonConstFunc(); // 错误不能调用非const成员函数return 0;
}在上述示例中constFunc()被声明为const成员函数因此可以被const对象调用。而nonConstFunc()是非const成员函数因此不能被const对象调用。
非const对象可以调用const成员函数吗
正确非const对象可以调用const成员函数。const成员函数的作用是表示该函数不会修改对象的状态。因此无论是const对象还是非const对象都可以调用不会修改对象状态的const成员函数。
示例
class MyClass {
public:void nonConstFunc() {// 可以修改对象状态的非const成员函数}void constFunc() const {// 不能修改对象状态的const成员函数}
};int main() {MyClass obj;obj.constFunc(); // 可以调用const成员函数obj.nonConstFunc(); // 也可以调用非const成员函数return 0;
}在上述示例中constFunc()是const成员函数因此可以被非const对象obj调用。同时非const成员函数nonConstFunc()也可以被非const对象obj调用。因为非const对象可以修改对象的状态所以可以调用const成员函数和非const成员函数。
const成员函数内可以调用其它的非const成员函数吗
在const成员函数内部只能调用其他const成员函数。const成员函数的作用是保证不修改对象的状态因此它们不能调用非const成员函数。如果在const成员函数内部调用非const成员函数编译器将会报错。
示例
class MyClass {
public:void nonConstFunc() {// 可以修改对象状态的非const成员函数}void constFunc() const {// 不能修改对象状态的const成员函数nonConstFunc(); // 错误! const成员函数不能调用非const成员函数}
};int main() {MyClass obj;obj.constFunc();return 0;
}在上述示例中constFunc()是const成员函数它尝试在内部调用了非const成员函数nonConstFunc()这将导致编译错误。
如果确实需要在const成员函数内部调用非const成员函数可以使用const_cast进行类型转换但是这样会绕过const的限制不推荐使用。
void constFunc() const {const_castMyClass*(this)-nonConstFunc(); // 可以调用非const成员函数但不推荐使用
}非const成员函数内可以调用其它的const成员函数吗
非const成员函数可以调用其他的const成员函数。在非const成员函数内部可以调用任何类型的成员函数包括const成员函数。这是因为非const成员函数可以修改对象的状态而const成员函数不允许修改对象的状态所以在非const成员函数内部调用const成员函数是安全的。
示例
class MyClass {
public:void nonConstFunc() {// 可以修改对象状态的非const成员函数constFunc(); // 可以调用const成员函数}void constFunc() const {// 不能修改对象状态的const成员函数}
};int main() {MyClass obj;obj.nonConstFunc(); // 调用非const成员函数它内部调用了const成员函数return 0;
}在上述示例中nonConstFunc()是非const成员函数它内部调用了const成员函数constFunc()这是允许的。因为非const成员函数可以修改对象的状态包括调用const成员函数不会破坏对象的const属性。
总结
权限缩小可以权限放大不可以即被const修饰的是可读的不被修饰的是可读可写的不被修饰的可以访问被修饰的
二、取地址及const取地址操作符重载
概念
这两个默认成员函数一般不用重新定义 编译器默认会生成。 不想知道太多的读者可以直接跳过。
class Date
{
public:Date* operator(){return this;}const Date* operator()const{return this;}
private:int _year; // 年int _month; // 月int _day; // 日
};这两个运算符一般不需要重载使用编译器生成的默认取地址的重载即可只有特殊情况才需要重载比如想让别人获取到指定的内容
示例
在C中const关键字用于修饰变量表示该变量的值不可修改。const修饰符同样也可以用于指针表示指针所指向的内容是不可修改的。
在C中对于指针类型可以重载取地址操作符来返回指针的地址。但是const修饰符的存在可能导致取地址操作符无法重载。
当一个指针被声明为const类型时取地址操作符不会返回指针的地址而是返回指针指向的内容的地址。这是因为const关键字修饰的指针表示其所指向的内容是不可修改的因此不需要返回指针的地址。
以下是一个示例代码展示了如何重载取地址操作符和处理const修饰符
#include iostreamclass MyClass {
private:int value;public:MyClass(int value) : value(value) {}int* operator() {std::cout Non-const operator std::endl;return value;}const int* operator() const {std::cout Const operator std::endl;return value;}
};int main() {MyClass obj(10);int* ptr1 obj; // 调用非const版本的operatorconst int* ptr2 obj; // 调用const版本的operatorreturn 0;
}输出结果为
Non-const operator
Const operator在上述代码中类MyClass重载了取地址操作符。它包含两个版本一个是非const版本另一个是const版本。
在main()函数中先后使用非const指针和const指针获取MyClass对象的地址。当使用非const指针时调用非const版本的operator而当使用const指针时调用const版本的operator。
通过重载取地址操作符我们可以根据指针的类型选择合适的操作。对于const修饰符我们还可以使用const版本的operator来获取指向内容的地址。