网站快排,阿里云wordpress安装教程,大黔门官方网站建设,永春网站设计C#xff1a;类与对象
注意#xff0c;这是笔记#xff0c;不是学习手册#xff01;#xff01;#xff01;有可能不适合别人阅读#xff0c;如果读者有什么问题欢迎在评论区提问#xff01;#xff01;
类与对象
不要把类看的多么高深莫测#xff0c;通过C语言中…C类与对象
注意这是笔记不是学习手册有可能不适合别人阅读如果读者有什么问题欢迎在评论区提问
类与对象
不要把类看的多么高深莫测通过C语言中类型和变量的方式来类比记忆。
类类型对象变量属性数据行为操作函数
在C中类可以看作一种自定义的类型和C的结构体很像。 对于这个类其中包含的每一个类型就是一个成员结构体中的类型也叫做类的属性对于每个成员都有可以对其进行操作的函数这个函数就叫做成员方法这个成员方法也叫做类的行为。
例子
类对象CatgarfieldDogodiePeoplehug 类是数据和行为的集合。 定义类与使用
class Cat{
};class Dog{
};class People{
};Cat garfield;
Dog odie;
People hug;例子
class People{// 属性string name;Day birthday;double height;double weight;void say(string word);void run(Location loc);
}/************************************************************************* File Name: class.cpp Author:Royi Mail:royi990001gmail.com Created Time: Fri 23 Feb 2024 07:56:13 PM CST Describe: ************************************************************************/#include iostream
#include algorithm
#include list
#include vector
#include queue
#include stack
#include set
#include map
#include cstdio
#include cstdlib
#include ctype.h
#include cmath
#include string
#include sstreamusing namespace std;class People {
public:string name;unsigned int age;char sex;void say() {cout My name is name;cout , Im age years old;if (sex m) {cout Im a boy! endl;} else {cout Im a girl endl;}}
};int main() {People hug;hug.name Captain Hu;hug.age 40;hug.sex m;hug.say();return 0;
}
类的作用
在程序设计时我们通过在类中规定一个值的界限而确定该对象的是否执行了合理的操作
#include iostream
#include algorithm
#include list
#include vector
#include queue
#include stack
#include set
#include map
#include cstdio
#include cstdlib
#include ctype.h
#include cmath
#include string
#include sstreamusing namespace std;class People {
public :void say() {cout name , age endl;}void set_name(string name) {this-name name;return ;}void set_age(int age) { // 一个人的名字不能为负数if (age 0) {perror(Invalid parameters);exit(1);} else {this-age age;return ;}}
private :string name;int age;
};int main() {People hug;hug.set_name(Royi);hug.set_age(40);hug.say();return 0;
}
访问权限
关键字作用类外对类内public公告访问权限所有人private私有访问权限自己protected受保护的访问权限自己和儿子friendly破坏私有可以访问类内的类外方法
属性设置成private只允许类内方法访问自己。
this
this是一个指针这个指针指向当前对象。
构造/析构函数
构造/析构函数使用方式默认构造函数People a;People(string name);People a(“hug”);People(const People a)拷贝构造与不等价~People();无
类的定义与销毁
先运行对象的构造函数执行完之后这个对象就算成立了。
当对象被销毁时会调用析构函数。
在类中会有一个默认的构造函数它没有任何参数编译器添加。 类只有在定义时才会调用构造函数。 有参构造和转换构造函数
有参构造在基础的构造函数中加入参数调用时传入参数转换构造只有一个参数的有参构造函数。给类提供了将其他类型的值隐式的转换为该类的方法。 显式的类型转换强制类型转换 隐式的类型转换程序中看不见是自动的 // ...
// 这是一个转换构造函数
A(int x) {cout transfer constructor endl;this-x x;this-y 0;
}// 调用时
void func(A a) {cout func :;a.output();return;
}// 如果调用
func(6);
// 也能通过编译这种情况下就使用了隐式的类型转换下面的代码也是转换构造
A a 4;
// 将4赋值给a类对象调用的是转换构造func(6) 函数在调用时实际上发生了这样的操作 func(A a 6) 拷贝构造函数
传入相同类型的一个对象的引用时将传入对象的值拷贝给当前对象。
//下面是一个拷贝构造函数
A(const A a) {cout copy constructor;this-x a.x;this-y a.y;
}int mian() {
A a; // 调用的a类的默认构造函数
A b a, c; // 调用的b类的拷贝构造函数调用的是c类的默认构造函数
c a; // 没有调用构造函数使用了c的赋值运算符符号但是需要重载
}注意只有定义类时才会调用构造函数 为什么拷贝构造函数一定要传入const类型的值
假设我们有一个 const 类型的类 const A a 如果
int mian() {const A a;A b a; // 调用了拷贝构造会报错
}因为 const A 表示“不能变”但是 表示可以变逻辑冲突。
为什么拷贝构造一定要传入引用
假设有这样的一行代码
A c a;我们期望调用 c 的拷贝构造函数但是如果 c 的拷贝构造函数中传入的不是引用将会是下面的结果
// 相当于将外部的a对象拷贝给参数列表中的a对象
A(const A a) {...
}这将会再次调用参数 A 对象的拷贝函数这样会发生递归。
构造函数与析构函数的具体执行流程
第一原则
先构造的后析构。先构造的对象有可能被后后构造的对象所依赖
类中属性的构造顺序和当前类的构造顺序
初始化列表
故名思意先给该类中的属性进行初始化。
class C{
public:// 初始化列表C(string n) : ch a, a(n .a), b(n .b) {name[this] n;name.output(this, class C constructor);}char chA a, b;~C() {name.output(this, class C destructor);}
}属性的构造顺序和当前类的构造顺序
属性先构造本身对象再构造。保证对属性的操作可执行
属性的构造顺序与初始化列表的顺序无关。
属性的构造顺序只与属性的声明顺序有关。
使用初始化列表的原则
初始化列表的使用顺序与声明顺序应当相同。
代码
展示了不同的方式定义的析构函数的用法
constructor.cpp
#include iostream
#include algorithm
#include list
#include vector
#include queue
#include stack
#include set
#include map
#include cstdio
#include cstdlib
#include ctype.h
#include cmath
#include string
#include sstreamusing namespace std;class A;
class MyMap : public mapA *, string {
public :void output(A *p, string s) {if (find(p) end()) {cout unknown name p;} else {cout operator[](p);}cout s endl;return ;}
} name;class A {
public :A() {name.output(this, default constructor);}A(int x) {name.output(this, transfer constructor);this-x x;this-y 0;}A(const A a) {name.output(this, copy constructor);this-x a.x;this-y a.y;}A(int x, int y) {name.output(this, 2 arguments constructor);this-x x;this-y y;}void operator(const A a) {name.output(this, operator);this-x a.x;this-y a.y;return ;}void output() {cout ( x , y ) endl;}~A() {name.output(this, destructor);}
private:int x, y;
};void func(A a) {cout func : ;a.output();return ;
}namespace copy_constructor {int main() {const A d;A a;A b a, c d;name[a] a;name[b] b;name[c] c;cout c a endl;c a;cout a a endl;cout b b endl;cout b c endl;return 0;
}}namespace test1 {
int main() {A a(3, 4), b(3), c 4;a.output();b.output();func(a);func(b);cout endl;func(6);return 0;
}
}
int main() {//test1::main();copy_constructor::main();return 0;
}
下面这个代码解释了构建与释放顺序
constructer_order.cpp:
#include iostream
#include algorithm
#include list
#include vector
#include queue
#include stack
#include set
#include map
#include cstdio
#include cstdlib
#include ctype.h
#include cmath
#include string
#include sstreamusing namespace std;class MyMap : public mapvoid *, string {
public :void output(void *p, string s) {if (find(p) end()) {cout unknown name p;} else {cout operator[](p);}cout s endl;return ;}
} name;class A {
public :A(string n) {name[this] n;name.output(this, class A constructor);}~A() {name.output(this, class A distructor);}
};class B {
public :B(string n) {name[this] n;name.output(this, class B constructor);}
};int main() {A a(a), b(b);return 0;
}