类和对象(C++对象模型和this指针,友元)
C++对象模型和this指针
在C++中,类内的成员变量成员函数分别存储,且只有非静态成员变量才会存储在类的对象上。
//2-7-1
#include<iostream>
using namespace std;
class example
{
//example构造函数
example()
{
exp1=0;
cout<<"example构造函数调用"<<endl;
}
//非静态成员变量占对象空间
int exp1;
//静态成员变量不占对象空间
static int exp2;
//函数也不占对象空间,所有函数都是共享的。
void func()
{
cout<<"func函数"<<endl;
}
//静态函数也是一样的
static void func2()
{
cout<<"func函数"<<endl;
}
};
int main()
{
cout<<"类占空间"<<sizeof(example)<<endl;;
}
输出结果:
类占空间4
如果我们把其他都注释掉,只留下exp1会发生:
输出结果:
类占空间4
this指针
C++提供了一个特殊的指针使得这个指针指向被调用的成员所属的对象,就是this指针。
this指针是隐含的,是无需自行定义的。
用途:
- 当形参和成员变量同名的时候用以区分,不过,这一点可以通过在命名规范来解决。(2-7-2)
- 在类的非静态成员函数中返回对象本身,可使用return *this(2-7-3)
//2-7-2
#include<iostream>
using namespace std;
class example
{
public:
void func(int a)
{
//this指针区分同名成员变量和形参
this->a=a;
}
int a;
};
int main()
{
example ex;
ex.func(10);
cout<<ex.a<<endl;
}
//2-7-3
#include<iostream>
using namespace std;
class example
{
public:
int a;
example& func(int a)
{
this->a=a;
return *this;
}
};
int main()
{
example ex;
ex.func(10).func(20);
cout<<ex.a<<endl;
}
C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针,否则会报错
//2-7-4
#include<iostream>
using namespace std;
class example
{
public:
int a;
example& func(int a)
{
this->a=a;
return *this;
}
};
int main()
{
example* ex=NULL;
ex->func(10).func(20);
cout<<ex->a<<endl;
}
上面这串代码会报错,因为空指针中不能调用成员函数,但是如果把func函数中的this指针去掉就不会报错。
const修饰成员函数
常函数
成员函数后加const修饰就是常函数void example() const{}
,常函数的特点是不能修改成员变量,只能读取成员变量。不可修改成员属性。成员属性声明时加关键字mutable后,在常函数中依然可以修改。
常对象
声明对象前加const称该对象为常对象,常函数只能调用常函数,常对象只能调用常函数。
//2-7-5
#include<iostream>
using namespace std;
class example
{
public:
example()
{
a=0;
}
int a;
example& func(int a)
{
this->a=a;
return *this;
}
void print() const
{
cout<<a<<endl;
}
//void newfunc(int a) const
//{
//this->a=a;常函数不能修改成员变量
//func(int a);常函数不能调用非常函数
//}
};
int main()
{
example ex;
ex.func(10).func(20);
ex.print();
cout<<ex.a<<endl;
const example ex2;
//ex2.func(10);常对象只能调用常函数
ex2.print();
}
友元
友元分为两种:全局函数做友元,类做友元。类做友元的时候,可以分为成员函数做友元,成员变量做友元。
在程序中,有时候需要访问类的私有成员,这时候就需要用到友元。友元的目的是为了访问类的私有成员。
以下是一个例子:
//2-8-1
#include<iostream>
using namespace std;
class example
{
friend void goodprint(example &ex);
public:
example(int a,int b)
{
this->a=a;
this->b=b;
}
private:
int a;
int b;
};
void goodprint(example &ex)
{
cout<<ex.a<<endl;
cout<<ex.b<<endl;
}
int main()
{
example ex(10,20);
goodprint(ex);
}
如果不加friend,就会因为权限问题,不可访问私有成员。
类做友元:
//2-8-2
#include<iostream>
using namespace std;
class example
{
friend class example2;
public:
example(int a,int b)
{
this->a=a;
this->b=b;
}
private:
int a;
int b;
};
class example2
{
public:
void print(example *ex)
{
cout<<ex->a<<endl;
cout<<ex->b<<endl;
}
};
int main()
{
example ex(10,20);
example2 ex2;
ex2.print(&ex);
}
成员函数做友元:
//2-8-3
#include<iostream>
using namespace std;
class example2;
class example
{
public:
example();
void print();
private:
example2 *ex;
};
class example2
{
public:
friend void example::print();
example2()
{
a = 10;
b = 20;
}
example2(int a, int b)
{
this->a = a;
this->b = b;
}
private:
int a;
int b;
};
example::example()
{
ex = new example2;
}
void example::print()
{
cout<<ex->a<<endl;
cout<<ex->b<<endl;
}
int main()
{
example2 ex(100,20);
example ex2;
ex2.print();
return 0;
}