本文主要是介绍c++中的特殊成员(const,stacic,友元,类间关系),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
- 1.初始化参数列表(特殊的构造函数的写法)
- 2. const成员
- 2.1 const 数据成员
- 2.2 const 成员函数
- 2.3 const 对象
- 3.静态数据成员
- 3.1 static数据成员
- 1.定义及初始化
- 2. 注意调用
- 3. 静态数据成员会保留上一次执行的结果
- 3.2 static成员函数
- 1. static 修饰的函数
- 2.static函数的调用
- 4. 友元关系
- 1. 友元函数
- 2.友元类
- 5. 类的组合
- 6. 类中成员函数指针
1.初始化参数列表(特殊的构造函数的写法)
与其他函数不同,构造函数除了有名字,参数列表和函数体之外,
还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段。
初始化参数列表 :构造函数名(参数1,参数2,…):成员1(参数1),成员2(参数2)…{}
初始化参数列表很重要
#include <string>
class MM
{
public://1.普通的构造函数写法,很少用MM(string name){this->name = name;}//2.初始化参数列表 --->很重要 如集成,类的组合常常使用MM(string name, int age) :name(name), age(age){}//构造函数名(参数1,参数2,...):成员1(参数1),成员2(参数2)....{}
protected:string name;int age;
};
初始化参数列表不能用this指针
//MM(string name, int age) :this->name(name), this->age(age){}//错误
2. const成员
const: 不能修改
2.1 const 数据成员
- 常数成员在构造函数时必须采用初始化参数列表的方式进行初始化
- num是常数据成员,必须采用初始化参数列表
- name,age是普通数据成员,可以用this指针,也可以用初始化列表
#include <string>
class MM
{
public:MM(string name, int age, int num) :num(num) //常数据成员{this->name = name; //普通数据成员this->age = age;}
protected:string name; //普通数据成员int age;const int num; //假如这是身份证号:必须使用初始化参数列表
};
普通数据成员,也可以用初始化列表
#include <string>
class MM
{
public:MM(string name, int age, int num) :name(name),age(age),num(0) {}//num可以初始化为一常数,这里举例为0
protected:string name; //普通数据成员,可随意int age;const int num; //常数据成员,必须使用初始化参数列表
};
- 构造函数必须要初始化常数据成员
#include <string>
class MM
{
public:MM(string name):num(0) //初始化列表的方式{this->name = name;}
protected:string name;int age;const int num; //必须使用初始化参数列表
};
- char*类型的初始化列表
#include<string>
class boy
{
public:boy(const char* str) :str(str) {}boy() :str("ILoveyou") {}const char* str;
};
2.2 const 成员函数
- 注意写法:const放在函数后面,只能写在类里面
- 注意限定:常成员函数不能修改数据成员
- 常成员函数可以和普通函数共存
#include <string>
class MM
{
public:MM(string name, int age, int num) :num(num) //构造函数完成初始化{this->name = name;this->age = age;} void print() //普通函数{cout << "普通函数" << endl;cout << name << ":" << age << endl;}void print() const //常成员函数{cout << "常函数" << endl;//可以使用数据成员,但是不能修改cout << name << ":" << age<<":"<<num << endl;}
protected:string name;int age;const int num; //必须使用初始化参数列表
};
2.3 const 对象
常对象只能调用常成员函数,普通对象优先调用普通函数
int main()
{ const MM mm("Love"); //常对象mm.print(); //常对象只能调用常成员函数MM myMM("小仙女", 18); //普通对象优先调用普通函数myMM.print();return 0;
}
3.静态数据成员
static修饰的变量成为静态变量,
3.1 static数据成员
1.定义及初始化
- 定义static变量时,需要前缀static,并且依旧受权限限定词(public, protected)限定
- static数据成员必须初始化,用类名前缀,不再需要static修饰
- static数据成员必须初始化,类似全局初始化,需要在类外进行初始化,也不能在主函数中初始化
class MM
{
public://初始化参数列表的方式比较多MM(string name) :name(name) {count++;}
protected:string name;
public:static int count; //需要前缀static,依旧受权限限定词限定};
//类外必须初始化,要用类名限定,不再需要static
int MM::count = 0; //用类名前缀
2. 注意调用
- 他的使用可以不需要对象 静态数据成员属于类,不属于对象
- 依旧受权限和类名限定词限定
- 类似于一个写在类里面的全局变量
class MM
{
public:MM(string name) :name(name) {}
protected:string name;
public:static int count;
};
int MM::count = 0;
int main() {
//静态数据成员依旧受权限限定词限定,count为受保护类型限定时,主函数会报错cout << MM::count << endl;return 0;
}
3. 静态数据成员会保留上一次执行的结果
class MM
{
public:MM(string name) :name(name) {count++;}
protected:string name;
public:static int count;
};
int MM::count = 0;
int main() {cout << MM::count ;MM mm1("yykk");MM mm2("oracle");MM mm3("LBW");cout << MM::count ;return 0;
}
总共调用了三次初始化列表
普通函数使用静态数据成员是可以随便使用的
3.2 static成员函数
static成员函数: static修饰的类内函数
通常用来写一些特定的接口,一些重写的函数
1. static 修饰的函数
类中实现
类中实现 statick+普通函数
class MM
{
public:static int count; //静态成员变量static void printInfo() //类中实现{.........} static void printData(MM object){......}
};
类外实现
- 类外实现的语法:
类外实现不需要static修饰,但是需要有类名限定
class MM
{
public:static int count; //静态成员变量static void printInfo(); //类外实现的声明static void printData(MM object);
protected:string name;
};
//类外实现不需要static修饰,需要类名限定
void MM::printInfo()
{......}
void MM::printData(MM object)
{.........}
- 调用与访问问题
- 调用: 不需要对象
- 静态函数访问静态数据成员,没有任何问题
- 静态成员函数访问非静态数据成员,通过指定对象,传参传一个对象进去指定
- 传参的静态成员函数也可以访问受保护的,私有的成员变量
class MM
{
public:static int count; //静态成员变量static void printInfo(); static void printData(MM object); //指定对象的函数声明
protected:string name;
};
void MM::printInfo() //未传参
{//静态函数访问静态数据成员,没有任何问题cout << count << endl;
}
void MM::printData(MM object) //传参
{//静态成员函数访问非静态数据成员,通过指定对象,否则无法访问cout << object.name << endl; //指定对象,可以访问具有保护属性,私有属性的成员变量cout << count << endl; //不需要指定对象
}
2.static函数的调用
静态函数的调用
可以通过 类名:: 进行调用,也可以通过 对象. 进行调用
#include <string>
class MM
{
public:MM(string name) :name(name) {} //初始化列表static void printInfo(); //未传参的静态成员函数static void printData(MM object); //传参的静态成员函数static int count; //静态成员变量
protected:string name;
};
int MM::count = 0; //静态成员变量的初始化
void MM::printInfo() //
{cout << count << endl;}
void MM::printData(MM object)
{cout << object.name << endl;cout << count << endl;}
int main() {MM mm1("yykk"); //定义两个对象MM mm2("oracle"); MM mm3("ojbk"); //静态函数的调用MM::printInfo(); //通过类进行调用MM::printData(mm3);mm2.printData(mm3); //通过对象进行调用mm1.printData(mm2);return 0;
}
4. 友元关系
1. 友元函数
friend关键字修饰的函数就是友元函数:
- 友元函数不属于类,可以在类中实现,也可以在类外实现
- 类外实现不需要friend修饰,不需要加类名限定,就当做普通函数写
- 类外实现需要在类内函数声明
- 友元函数是在当前函数中赋予对象具有打破类的权限限定的作用,即在这个函数中,所使用的对象具有访问当前类的任何属性,保护私有都可以访问,打破类的隐藏和封装性
- 传参的对象/对象指针
- 在函数体创建对象
- 单个类的友元函数可以函数重载
class MM
{friend void makeBoyFriend(); //类内函数声明friend void makeBoyFriend(MM object); //函数重载
public:MM(string name, int age, int money) :name(name), age(age), money(money) {}string name;
protected:void print() {cout << name << ":" << age << ":" << money << endl;}int age;
private:int money;
};
void makeBoyFriend() //不需要friend,不需要类名限定
{//在当前函数中任何对象都具有打破类的权限限定MM boy("yykk", 18, 100); //能够访问类内任何属性boy.print();cout << boy.name << ":" << boy.age << boy.money << endl;
}
*以另一个类的成员函数为友元函数
- 用类名限定
- 要声明一下
- 实现顺序问题
#include<iostream>
#include<string>
using namespace std;
class Girl;
class Boy
{
public:void makeGirlFriend(Girl girl);
protected:
};
class Girl
{ friend void Boy::makeGirlFriend(Girl girl);
public:Girl(string name, int age) :name(name), age(age) {}string name;
protected:int age;
};
void Boy::makeGirlFriend(Girl girl)
{cout << girl.name << ":" << girl.age << endl;}
int main()
{ Girl girl("Oracle", 19);Boy boy;boy.makeGirlFriend(girl);return 0;
}
2.友元类
下面代码中Boy类就是Girl类的友元类
class Girl
{friend class Boy;
public:......
protected:......
};
class Boy
{
public:.......
protected:.......
};
在Boy类的任何地方girl对象都可以访问girl任何属性
class Girl
{ friend class Boy;
public:Girl(string name, int age) :name(name), age(age) {}string name;
protected:int age;
};
class Boy
{public:void print() //两种打印的方式{ Girl girl("Oracle", 18);//在当前类的任何地方girl对象都可以访问girl任何属性cout << girl.name << ":" << girl.age << endl;}void print(Girl object) {cout << object.name << ":" << object.age << endl;}
protected:
};
*互为友元,A类和B类互为友元类
class A
{friend class B;
public:
protected:
};
class B
{friend class A;
public:
protected:
};
5. 类的组合
以另一个类的对象为数据成员:
- 构造函数写法
- 必须初始化参数列表方式调用组合类的构造函数
- 组合类必定会调用其他类的组合
- 构造和析构顺序问题
#include <iostream>
using namespace std;
class Clothes
{
public:Clothes(int color) :color(color) {cout << "A" << endl;}
protected:int color;
};
class Cosmetics
{
public:Cosmetics(int moeny) :money(money) {cout << "B" << endl;}
protected:int money;
};
class MM
{
public://MM(string name,int color,int money) :Cosmetic(money), Clo(color){ this->name = name;cout << "C" << endl;}
protected:string name;//构造顺序和这个声明顺序有关Clothes Clo; Cosmetics Cosmetic;
};
int main()
{MM mm("LBW",1,2); //A B Creturn 0;
}
6. 类中成员函数指针
#include <iostream>
using namespace std;
class MM
{
public:MM(string name, int age) :name(name), age(age) {}void print() {cout << name << "\t" << age << endl;}
protected:string name;int age;
};
int main()
{MM mm("Bug", 10);//error C3867: “MM::print”: 非标准语法;请使用 "&" 来创建指向成员的指针//1. "&" 来创建指向成员的指针 &MM::print//错误写法 void MM::(*p)()//错误写法 void (*MM::p)(); void (MM:: * p)() = &MM::print;(mm.*p)(); //调用的时候写法上注意点return 0;
}
这篇关于c++中的特殊成员(const,stacic,友元,类间关系)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!