成员
常成员函数
初始化列表
静态成员
常成员函数
在C++中,被const
关键词修饰的对象只能在初始化时赋值,此后不能被修改。并且,对象的成员也不能被修改;
#include <iostream>
using namespace std;
class Node{
public:
int value;
};
int main(){
const Node node;
//node.value = 11;编译错误,const对象成员对象无法被修改赋值
return 0;
}
除了不能直接修改const对象的成员外,也不能通过调用成员函数的方式修改对象的成员
#include <iostream>
using namespace std;
class Node{
public:
void modify(int v){
value = v;
}
private:
int value;
};
int main(){
const Node node;
//node.modify();编译错误,const对象即使使用调用成员函数的方式也不能修改成员
return 0;
}
const对象无法调用普通成员函数,究其本质原因,在于普通成员函数的__thiscall调用中this
指针的类型与const对象不一致
普通成员函数的this指针类型为TypeClass * const this
this是常量指针,无法被修改指向,但是能通过this指针修改成员值。而若要能做到无法通过this指针修改成员值,则需要this指针的类型为cosnt TypeClass * const this
,因此普通成员函数不满足要求.
#include <iostream>
using namespace std;
class Node{
public:
Node(int v = 0):value(v){}
int GetValue()const{
return value;//this指针类型为 const Node* const this
}
private:
int value;
};
int main(){
//const成员函数,无论是否为const对象都能调用
const Node node(11);
cout<<node.GetValue()<<endl;//11
Node noed2(12);
cout<<node2.GetValue()<<endl;//12
return 0;
}
初始化列表
C++提供构造函数用来初始化成员,但是如果成员中存在C++类类型的成员,则无法直接在构造函数体内对对象进行初始化(只能进行新创建),此外还有对const成员动态初始化等,因此,C++提供了构造函数的初始化列表语法
#include <iostream>
using namespace std;
class Tnode{
public:
Tnode(int tnv = 0):tnode(tnv){}
private:
int tnode;
};
class Node{
public:
Node(){}
Node(int v,int _mid,int tnv):value(v),mid(_mid),tnode(tnv){
//不能在构造函数体内部对const成员赋值,也无法调用对象成员的带参构造函数初始化对象
//当然,可以这样写,但是会多创建一个无用的临时对象
tnode = Tnode(12);
}
private:
int value;
const int mid;
Tnode tnode;
};
int main(){
Node node(11,22,33);
return 0;
}
初始化列表处理能处理成员的初始化外,也能解决构造函数的相互调用问题
#include <iostream>
using namespace std;
class Node{
public:
Node(int value,int mid):value(value),mid(mid){}
//运用已存在的构造函数实现新的构造函数,不能在新的构造函数体内调用已存在的构造函数,那样就成了创建新的临时对象了
Node(int value):Node(value,0){}
Node():Node(0,0){}
private:
int value;
int mid;
};
int main(){
Node node;
Node node2(11);
Node node3(11,22);
return 0;
}
关于使用初始化列表对对象成员的初始化,类的成员对象的初始化时机与在初始化列表中的位置无关。类内部的对象成员初始化时机取决于其在源码中的位置。最先定义的对象最先被初始化,后定义的对象被后初始化,这些对象要先于本体对象被初始化,而后于本体对象被析构。
#include <iostream>
using namespace std;
class TTnode{
public:
TTnode(int v = 0){}
~TTnode(){}
};
class Node{
public:
Node():tnode(11),tnode2(22),tnode3(33){}
private:
TTnode tnode;
TTnode tnode2;
TTnode tnode3;
};
int main(){
//node对象中有3个TTnode对象,node对象与TTnode这3个对象间的构造与析构顺序是
//构造顺序:tnode、tnode2、tnode3、node
//析构顺序:node、tnode3、tnode2、tnode
Node node;//最先构造的最后释放,最后构造的最先释放
return 0;
}
静态成员与静态成员函数
在C语言中,无论是全局变量还是静态全局变量,其内存都在数据区,并且当进程创建时便存在。内存独一份。
全局变量的作用域是工程项目的所有源文件中,而这就导致全局变量非常容易滥用,从而造成项目的可维护性大打折扣。而C++中,则提供了静态成员这样类型,可以认为是带有命名空间访问受限的全局变量。
C++中的静态成员内存也是在高地址的数据区,与普通全局变量或者静态变量的内存区域并无区别。
#include <iostream>
using namespace std;
class Node{
public:
static int value;
};
//定义静态成员时初始化时只能在类外部初始化,静态成员必须被初始化,无论创建多少新node对象,静态成员内存value永远只有一份
int Node::value = 0;
int main(){
Node node1;
node1.value = 11;
Node node2;
node2.value = 22;
//value的你内存是数据区中的,独一份,因此不管通过哪个对象对其进行修改,都是修改同一份内存
cout<<node1.value<<endl;//22
//由于value内存属于全局区,因此对其访问跟对象并没有关系,并不需要通过对象实例去访问静态成员,所以常见的使用方式是直接通过类名进行访问
Node::value = 11;
cout<<Node::value<<endl;//11
Node::value = 22;
cout<<Node::value<<endl;//22
return 0;
}
静态成员是受限的全局变量,除了需要通过类名进行访问外,还可以设置静态成员的访问权限,这样进一步对其进行了访问限制
#include <iostream>
using namespace std;
class Node{
public:
void SetValue(int v){
if(v > 0){
value = v;
}
}
int GetValue(){
return value;
}
private:
static int value;
};
int Node::value = 0;
int main(){
//Node::value = 11;编译错误,无法直接访问静态成员,虽然其属于数据区内存,但被private限制了访问,只能通过函数访问
Node node;
node.SetValue(11);
//虽然能通过对象访问value,但是需要先创建node对象,这显然是不合理的
cout<<node.GetValue()<<endl;//11
return 0;
}
静态成员函数,无需先创建对象,可以直接通过对象名来调用函数(但无法通过对象来调用静态成员函数,其调用约定 并不相同)
#include <iostream>
using namespace std;
class Node{
public:
//静态成员函数,并不遵循__thiscall调用约定,也不能通过node对象调用此函数,并没有this指针传入
static void SetValue(int v){
if(v > 0){
value = v;
}
//demoV = 0;编译错误,静态成员函数内部并没有this指针,因此无法修改对象的成员
}
static int GetValue(){
return value;
}
private:
static int value;
int demoV;
};
int Node::value = 0;
int main(){
Node node;
//node.SetValue(11);编译错误,无法通过对象调用静态成员函数
Node::SetValue(11);
cout<<Node::GetValue()<<endl;//11
return 0;
}
通常,静态成员变量配合静态成员函数使用(在某些编程语言中,静态成员变量又被称为类变量,静态成员函数又被称为类方法)
posted on 2021-12-28 00:27 shadow_fan 阅读(277) 评论(0) 编辑 收藏 举报