目录
[【4】const 关键字](#【4】const 关键字)
[2》 修饰对象](#2》 修饰对象)
【1】作用域限定符::
1》名字空间
名字空间是一种代码的层级划分。
cpp
#include <iostream>
using namespace std;
// C++课程中几乎所有的类型(不包括基本数据类型)都在std中
int a = 1;
// 新建一个名字空间
namespace my_space {
int a = 3;
string s = "哈哈哈";
}
namespace my_space2 {
int a = 4;
string s = "嘿嘿嘿";
}
// 使用自己的名字空间
using namespace my_space2;
int main()
{
int a = 2;
std::cout << "你好" << std::endl;//像cout cin endl这些都属于std名字空间的内容,使用了std名字空间之后就不再需要加std::了
cout << a << endl; // 2
cout << ::a << endl; // 1
// 访问my_space的内容
cout << my_space::a << my_space::s << endl;//加上名字空间说明调用的是哪一个名字空间的变量
// 访问my_space2的内容
cout << my_space2::a << s << endl;//使用my_space2名字空间后就不再需要加作用域限定符来区分了
return 0;
}
2》类内声明,类外定义
函数是可以声明定义分离的,成员函数也可以声明定义分离,把成员函数的声明放置在类内,把成员函数的定义放在类外,因为定义在类外,所以需要加上**类名::**来指定定义的函数是哪一个类的。
cpp
#include <iostream>
using namespace std;
class Student
{
private:
string name;
public:
// 类内声明
Student(string n);
string get_name();
void set_name(string n);
};
// 类外定义
Student::Student(string n)//加上作用域限定符来指定是哪一个类的函数
{
name = n;
}
string Student::get_name()
{
return name;
}
void Student::set_name(string n)
{
name = n;
}
int main()
{
Student s("欢欢");
s.set_name("刘欢");
cout << s.get_name() << endl;
return 0;
}
【2】this关键字
1》概念
this在类中表示一个指针:this指针,是一种特殊的指针,保存了当前类对象的首地址(指向当前类的对象)
cpp
#include <iostream>
using namespace std;
class Student
{
private:
string name;
public:
Student(string n):name(n)
{
cout << this << endl;//输出当前对象的地址
}
string get_name()
{
cout << this << endl;//每次调用都看一下地址是多少
return name;
}
void set_name(string n)
{
cout << this << endl;
name = n;
}
};
int main()
{
//栈内存对象
Student s("欢欢");
cout << &s << endl;//直接取对象的地址
s.set_name("刘欢");
cout << s.get_name() << endl;
cout << endl;
//堆内存对象
Student* s2 = new Student("hh");
cout << s2 << endl;
cout << s2->get_name() << endl;
return 0;
}
2》调用成员
cpp
#include <iostream>
using namespace std;
class Student
{
private:
string name;
public:
Student(string n)
{
this->name = n;//通过this调用的对象时当前类的对象
cout << this->get_name() << endl;
}
string get_name()
{
return this->name;
}
void set_name(string n)
{
this->name = n;
}
};
多数情况下在类内调用成员的时候(除去有可能出现重名的情况),如果程序员不写this指针,编译器都会在成员调用时自动添加this指针。
3》区分重名的成员变量与局部变量
cpp
#include <iostream>
using namespace std;
class Student
{
private:
string name;
public:
Student(string name)//由于这时传过来的局部变量和成员变量重名,
// 所以这时就可以通过添加this指针来区分哪个是成员变量,哪个是局部变量
{
this->name = name;
}
string get_name()
{
return name;
}
void set_name(string name)
{
this->name = name;
}
};
int main()
{
Student s("Tom");
cout << s.get_name() << endl;
s.set_name("Jerry");
cout << s.get_name() << endl;
return 0;
}
4》链式调用
如果一个成员函数的返回值是当前类型的引用,说明这个函数支持链式调用,return的内容一定是*this。
cpp
#include <iostream>
using namespace std;
class Value
{
private:
int value;
public:
Value(int value)
{
this->value = value;
}
Value& add(int value)//返回值是一个Value类的引用
{
this->value += value;
return *this;//所以返回的时候是一个类对象
}
int get_value()
{
return value;
}
};
int main()
{
Value v1(0);
// 普通的调用方式:分步操作
v1.add(1);
v1.add(2);
v1.add(4);
v1.add(7);
cout << v1.get_value() << endl; // 14
cout << endl;
Value v2(0);
// 链式调用
//v2.add(1)执行完之后返回的仍然是一个对象,所以可以继续调用add函数,形成一个链式结构
cout << v2.add(1).add(2).add(4).add(7).get_value() << endl; // 14
cout << v2.get_value() << endl; // 14
return 0;
}
【3】static关键字
1》静态局部变量
使用static修饰的局部变量就是静态局部变量 ,所在的函数第一次被调用时创建 ,直到程序运行结束才销毁 ,所有的对象共用这一个静态局部变量。
cpp
#include <iostream>
using namespace std;
class Test
{
public:
void test_static()
{
int a = 1;
static int b = 1; // 局部静态变量,这个语句只有第一次执行到的时候会执行一次,之后就不会在执行了,
//所以在后面值发生变化之后再运行到这也不会再初始化
cout << a++ << endl;
cout << b++ << endl << endl;
}
};
int main()
{
Test t1;
Test t2;
t1.test_static();//1 1
t2.test_static();//1 2
t1.test_static();//1 3
return 0;
}
2》静态成员变量
使用 static 关键字修饰的成员变量就时静态成员变量。
静态成员变量有以下特点:
1.非 const 修饰的静态成员变量不能再类内初始化,必须在类外初始化。
2.同一个类的所有对象共享一份静态成员变量。
3.静态成员变量可以直接通过类名调用,无需关联任何对象,因为静态成员变量在程序执行时创建,在程序结束时销毁。
cpp
#include <iostream>
using namespace std;
class Test
{
public:
int a = 1; // 成员变量
static int b; // 静态成员变量
};
int Test::b = 1; // 类外初始化
int main()
{
// 通过类名直接调用静态成员变量
cout << Test::b << " " << &Test::b << endl;
Test t1;
Test t2;
cout << t1.a++ << " " << &t1.a << endl;
cout << t2.a++ << " " << &t2.a << endl;//t1和t2的变量a是各自拥有的,所以地址不同
cout << t1.b++ << " " << &t1.b << endl;
cout << t2.b++ << " " << &t2.b << endl;//变量b是静态成员变量,共有的,所以t1和t2的b地址相同,和直接类名调用一样
return 0;
}
3》静态成员函数
使用static 关键字修饰的成员函数就是静态成员函数。
静态成员函数有以下特点:
1.没有this 指针,因此不能调用非静态成员。
2.如果静态成员函数声明与定义分离,static 只需要写在声明处即可。
3.除了可以使用对象调用外,还可以直接通过类名::调用。
cpp
#include <iostream>
using namespace std;
class Test
{
public:
int a = 1;
static int b;
static void func(); // 静态成员函数,声明的时候写了 static关键字
};
int Test::b = 1;
void Test::func() // 类外定义,定义的时候就不再需要写 static 关键字
{
// cout << a << endl; 错误,a不是静态成员变量,不能被静态成员变量调用
cout << b << endl;
}
int main()
{
Test t;
t.func();//类对象调用
Test::func();//类名直接调用
return 0;
}
【4】const 关键字
1》修饰成员函数
const修饰的成员函数,表示常成员函数,可以调用非 const 的成员变量,但是不能修改数值,不能调用非 const 的成员函数。
如果成员函数的声明与定义分离,const在声明和定义处都要写。
cpp
#include <iostream>
using namespace std;
class Test
{
private:
string name;
public:
void set_name(string name)
{
this->name = name;
}
string get_name() const; // 常成员函数
void test_const() const // 常成员函数
{
// set_name("哈哈哈"); 错误,set_name不是常成员函数,不能调用
cout << get_name() << endl;
cout << name << endl;
// name = "你好"; 错误
}
};
string Test::get_name() const // 类外定义,即使声明的时候加了const,在定义时也要加const
{
return name;
}
int main()
{
Test t;
t.set_name("再见");
t.test_const();
return 0;
}
一般只要成员函数不修改属性值就使用 const 修饰,以提高代码的安全性。
2》 修饰对象
const 修饰对象表示该对象时常量对象,这样的对象的成员变量数值不可变,不能调用任何非 const 修饰的成员函数。
cpp
#include <iostream>
using namespace std;
class Test
{
public:
// string name = "张三"; // 直接初始化可以
string name;
// Test(string name)
// {
// this->name = name; // 构造函数函数体初始化可以
// }
Test(string name):name(name){}
void set_name(string name)
{
this->name = name;
}
string get_name() const
{
return name;
}
};
int main()
{
// const可以放在类型前后
Test const t1("张三");
// t1.set_name("你好"); 错误,set_name不是const修饰的函数,不可调用
const Test t2("李四");
// t2.name = "你好"; 错误
cout << t1.get_name() << endl;
cout << t2.get_name() << endl;
return 0;
}
3》修饰成员变量
const 修饰的成员变量表示常成员变量,这样的成员变量不允许被修改。
常成员变量的初始化方式有两种:
1.直接初始化
2.构造初始化列表(优先级更高)
cpp
#include <iostream>
using namespace std;
class Test
{
public:
const string name = "张三"; // 直接初始化
Test(){}
Test(string name):name(name) // 构造初始化列表
{}
// Test(string name)
// {
// this->name = name; 错误
// }
void set_name(string name)
{
// this->name = name; 错误
}
string get_name() const
{
return name;
}
};
int main()
{
Test t0;
cout << t0.get_name() << endl;
Test t("王五");//由于初始化列表的优先级更高,所以"王五"覆盖掉了"张三"
cout << t.get_name() << endl;
return 0;
}
今天的分享就到这里结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话点个关注支持一下吧!