简单定义类

#include <iostream>
#include <string> using namespace std; class Student
{
public:
int uid;
char *name;
int age; public:
void set(int id, char *name, int age)
{
this->uid = id;
this->name = name;
this->age = age;
}
void display()
{
cout << this->uid << this->name << this->age << endl;
}
}; void Call(const Student &ptr)
{
cout << ptr.name << endl;
} int main(int argc, char *argv[])
{
Student stu; // 实例化 stu.set(1001, "lyshark", 23); // 设置数据
cout << stu.uid << stu.name << stu.age << endl; // 输出
stu.display(); // 使用成员函数输出 Student *ptr = &stu; // 使用指针
cout << ptr->uid << ptr->name << ptr->age << endl; Call(stu);
system("pause");
return 0;
}

构造/析构 函数: 构造函数与类名相同,没有返回值,不写void,可以发生重载,可以有参数

#include <iostream>
#include <string> using namespace std; class Student
{
public:
int uid;
char *name;
int age; public:
Student(int uid,char *name,int age) // 构造函数
{
this->uid = uid;
this->name = name;
this->age = age;
}
~Student() // 析构函数
{
cout << "执行结束,析构 !" << endl;
}
void Display()
{
cout << this->name << endl;
} }; int main(int argc, char *argv[])
{ class Student *stu_ptr[3]; Student stu1(1001, "admin", 22);
Student stu2(1002, "guest", 33);
Student stu3(1003, "tudyit", 25); stu_ptr[0] = &stu1;
stu_ptr[1] = &stu2;
stu_ptr[2] = &stu3; for (int x = 0; x < 3; x++)
stu_ptr[x]->Display(); system("pause");
return 0;
}

析构函数,没有返回值,不可以写参数,不能发生重载,多用于最后的类的清理左右。

无参数构造函数(默认构造函数),有参数

拷贝构造函数:

#include <iostream>
#include <string> using namespace std; class Student
{
public:
int uid;
char *name;
int age; public:
Student(int uid,char *name,int age) // 构造函数
{
this->uid = uid;
this->name = name;
this->age = age;
}
Student(const Student& ptr) // 拷贝构造函数
{
name = ptr.name; // 将 拷贝参数赋值给被拷贝类中
cout << "kaobei" << endl;
}
}; int main(int argc, char *argv[])
{
Student stu1(1001, "admin", 22); // 拷贝构造函数:括号法调用
// 调用拷贝构造函数 stu1 拷贝到stu2中
Student stu2(stu1);
cout << stu2.name << endl; Student stu3 = Student(stu1);
cout << stu3.name << endl; system("pause");
return 0;
}

浅拷被: 容易崩溃,系统简单的传值,出现问题。

#include <iostream>
#include <string> using namespace std; class Student
{
public:
char * m_name;
int m_age; public:
Student()
{ }
Student(char * name, int age)
{
m_name = (char *)malloc(strlen(name) + 1);
strcpy(m_name, name);
}
~Student()
{
if (m_name != NULL)
free(m_name);
} }; int main(int argc, char *argv[])
{
Student stu1("lyshark",25);
// < 浅拷贝,出现了崩溃的问题> 因为执行了两次析构,出现了冲突
Student stu2(stu1); // 调用拷贝构造函数 system("pause");
return 0;
}

深拷贝: 自己开辟堆空间,然后自己在拷贝构造函数中拷贝数据,防止冲突,同样的代码不会出现问题了。

#include <iostream>
#include <string> using namespace std; class Student
{
public:
char * m_name;
int m_age; public:
Student()
{ }
Student(char * name, int age)
{
m_name = (char *)malloc(strlen(name) + 1);
strcpy(m_name, name);
}
~Student()
{
if (m_name != NULL)
free(m_name);
}
Student(const Student &ptr)
{
m_age = ptr.m_age;
m_name = (char *)malloc(strlen(ptr.m_name) + 1);
strcpy(m_name, ptr.m_name); // 深层拷贝
}
}; int main(int argc, char *argv[])
{
Student stu1("lyshark",25);
// < 浅拷贝,出现了崩溃的问题> 因为执行了两次析构,出现了冲突
Student stu2(stu1); // 调用拷贝构造函数 system("pause");
return 0;
}

多个对象的构造和析构:初始化列表

#include <iostream>
#include <string> using namespace std; class Student
{
public:
char * m_name;
int m_age; public:
Student(char * x, int y) :m_name(x), m_age(y){}
}; int main(int argc, char *argv[])
{
Student stu("lyshark",23);
cout << stu.m_name << stu.m_age << endl; system("pause");
return 0;
}

explicit 关键字的作用 该关键字为了防止隐世类型转换,就是防止你瞎搞。

#include <iostream>
#include <string> using namespace std; class MyString
{
public:
char * m_Str; public:
MyString(const char *str)
{ }
// 该关键字为了防止隐世类型转换
explicit MyString(int num)
{ } }; int main(int argc, char *argv[])
{
MyString str = "lyshark"; // 显示调用 // MyString str2 = 10; system("pause");
return 0;
}

new 动态对象创建: 忘记 malloc() /free 吧,new 可以自动分配初始化空间,非常方便。开辟空间到堆。

#include <iostream>
#include <string> using namespace std; class Student
{
public:
char * m_Str; public:
Student()
{
cout << "默认构造调用" << endl;
}
~Student()
{
cout << "默认析构调用" << endl;
}
}; int main(int argc, char *argv[])
{
// Student stu1; // 在站区开辟空间 // 所有new出来的对象都会返回该类型的指针
// malloc 返回 void* 还必须要强转
// new 会调用构造函数? new 并不是函数而是运算符 Student *stu2 = new Student; // 堆区开辟空间
// 释放堆空间
delete stu2; // new 来开辟数组 , 他一定会调用默认构造函数,有多少数组成员就调用多少次!
Student *pArray = new Student[10]; pArray[0].m_Str = "lyshark"; cout << pArray[0].m_Str << endl; // 释放整个数组,必须加[] 中括号
delete [] pArray; system("pause");
return 0;
}

静态成员变量: static声明就是静态成员变量,无论建立多少对象,都只有一个静态数据的拷贝,所有对象都共享这个静态数据。

#include <iostream>

using namespace std;

class Student
{
public:
// 静态成员变量,在类内声明,在类外初始化
static int m_number; // 定义静态变量
}; int Student::m_number = 100; // 类外初始化实现 int main(int argc, char *argv[])
{
Student stu1, stu2; stu1.m_number = 200; // stu1赋值后,会影响stu2里面的,两个是共享数据的 cout << stu1.m_number << endl;
cout << stu2.m_number << endl;
cout << "通过类名直接访问:"<< Student::m_number << endl; system("pause");
return 0;
}

静态成员函数:

#include <iostream>

using namespace std;

class Student
{
public:
static void Display()
{
cout << "hello lyshark" << endl;
}
}; int main(int argc, char *argv[])
{
Student stu1,stu2; // 静态成员函数,不可以访问普通成员变量
// 但是可以访问静态成员变量 stu1.Display(); // 两个对象同样是调用的一个函数。
stu2.Display(); system("pause");
return 0;
}

单例模式设计思想: 一个类中,是能实例化出一个对象,这样就可以防止冲突的情况发生。

想想,如何实现,不论new多少次,始终只能保证,创建一个对象,不多创建。

#include <iostream>

using namespace std;

// 创建列中的对象,并且保证只有一个对象可以使用,一个对象实例。

class ChairMan
{
private:
// 1.将构造函数自由化,改成private
//
ChairMan(){ cout << "create super" << endl; }
public:
static ChairMan *singleMan; }; ChairMan * ChairMan::singleMan = new ChairMan; int main(int argc, char *argv[])
{
cout << "main" << endl; // 主席创建,先于 main
ChairMan::singleMan; ChairMan *cm1 = ChairMan::singleMan; system("pause");
return 0;
}

安全的改进

#include <iostream>

using namespace std;

// 创建列中的对象,并且保证只有一个对象可以使用,一个对象实例。

class ChairMan
{
private:
// 1.将构造函数自由化,改成private
//
ChairMan(){ cout << "create super" << endl; }
ChairMan(const ChairMan &ch) {};
private:
static ChairMan *singleMan;
public:
// 通过提供的接口实现访问
static ChairMan* getInstance()
{
return singleMan;
}
}; ChairMan * ChairMan::singleMan = new ChairMan; int main(int argc, char *argv[])
{
ChairMan * cm1 = ChairMan::getInstance();
ChairMan * cm2 = ChairMan::getInstance();
if (cm1 == cm2)
cout << "相等" << endl; // 现在其实也能改? 下面可以强改,加上拷贝构造,直接完事。
ChairMan *cm3 = new ChairMan(*cm2);
if (cm2 == cm3)
cout << "不相等" << endl; system("pause");
return 0;
}

打印机的单例模式案例。

#include <iostream>
#include <string> using namespace std; class Printer
{
private:
static Printer * singlePrinter; private:
Printer(){ };
Printer(const Printer & ptr); public:
static Printer * getInstance()
{
return singlePrinter;
}
static void PrintText(string text)
{
cout << text << endl;
}
}; Printer * Printer::singlePrinter = new Printer; int main(int argc, char *argv[])
{
// 拿到打印机对象指针,后期通过该指针操作数据
Printer * ptr = Printer::getInstance(); ptr->PrintText("hello lyshark"); // 调用打印机 system("pause");
return 0;
}

this 指针: this指针指向被调用的成员函数所属的对象,

#include <iostream>
#include <string> using namespace std; class Person
{
public:
char *name;
int age; public:
Person(char *p_name, int p_age) { this->name = p_name; this->age = p_age; } void Compare_Age(Person & ptr) // 对比年龄是否相等
{
if (this->age == ptr.age)
cout << "Same age" << endl; // 年龄相同
else
cout << "Same not age" << endl; // 年龄不同
} void PlusAge(Person & ptr) // 两个年龄相加
{
this->age += ptr.age;
} Person & Push_Age(Person &ptr)
{
this->age += ptr.age;
return *this; // 返回指向对象本体
} }; int main(int argc, char *argv[])
{
Person per1("lyshark", 33);
Person per2("admin", 33);
// ----------------------------------------
per1.Compare_Age(per2); // 判断两个类年龄是否相等
// ----------------------------------------
per1.PlusAge(per2); // 将两个年龄相加
cout << per1.age << endl; // 输出年龄
// ---------------------------------------- per1.Push_Age(per2).Push_Age(per2); // 链式编程(必须传递引用)
cout << per1.age << endl; system("pause");
return 0;
}

空指针访问成员函数: 如果用不到this则可以调用,用到的话就会报错。

#include <iostream>
#include <string> using namespace std; class Person
{
public:
int m_age; public:
void show() { cout << "person show" << endl; }
void show_age()
{
if (this == NULL) // 防止使用空指针访问
return;
cout << "show: "<< m_age << endl;
}
}; int main(int argc, char *argv[])
{ Person *ptr = NULL; ptr->show(); // 这个可以
ptr->show_age(); // 不可以 // show_age() 默认会加上 this --> 那么如果传递空指针则失败
// 代码接收空指针,会溢出 system("pause");
return 0;
}

常函数、常对象: 使用const 修饰成员函数,则是常函数,

#include <iostream>
#include <string> using namespace std; class Person
{
public:
int m_x;
int m_y; public:
Person()
{
this->m_x = 0;
this->m_y = 0;
} void showInfo() const // 声明常函数,函数内部不可有修改指针的指向
{
// this->m_x = 1000; 相当于修改成了: --> const Person * const this
cout << this->m_x << endl;
cout << this->m_y << endl;
}
}; int main(int argc, char *argv[])
{
Person per1;
per1.showInfo(); // 定义常对象,常对象不允许修改数据。
const Person per2; system("pause");
return 0;
}

友元函数的定义(全局函数): 将全局函数定义为友元函数,让外部函数,可以访问类内部的私有数据。

#include <iostream>
#include <string> using namespace std; class Building
{ friend void goodGay(Building *building);
private:
string m_badRoom; // 私有的卧室
string m_sittingRoom; // 客厅 public:
Building()
{
this->m_sittingRoom = "客厅";
this->m_badRoom = "卧室";
}
}; // 全局函数,我想让他能访问到私有的卧室
void goodGay(Building *building)
{
cout << "访问我的客厅:" << building->m_badRoom << endl;
cout << "访问我的卧室:" << building->m_sittingRoom << endl; } int main(int argc, char *argv[])
{
Building *building = new Building;
goodGay(building); system("pause");
return 0;
}

让整个类做友元类:

#include <iostream>
#include <string> using namespace std; class Teacher
{
friend class Student; // 让Student学生,可以访问我的私有成员 private:
char * m_school; // 老师所在的学校
char * m_class; // 老师所教的班级 public:
Teacher()
{
this->m_school = "中心小学";
this->m_class = "一年级二班";
}
}; class Student
{
private:
Teacher *ptr; // 设置一个指向teacher的指针 public:
Student()
{
ptr = new Teacher; // 初始化一下
}
void Display()
{
cout << "学生访问到的学校: " << this->ptr->m_school << endl;
cout << "学生访问到的班级: " << this->ptr->m_class << endl;
}
}; int main(int argc, char *argv[])
{ Student stu;
stu.Display(); system("pause");
return 0;
}

C/C++ 类与构造析构等知识的更多相关文章

  1. C++ 类、构造析构、深拷贝

    1st,感性理解类的思想,就是把数据和对数据的操作打包在一块儿,设计类的时候要 想好数据部分和 要进行的操作.以下是时间类的示意,时间包含时分秒,Time为构造函数,该类支持的操作就是设置时间和读取时 ...

  2. 转:Delphi2010新发现-类的构造和析构函数功能

    Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...

  3. Delphi2010新发现-类的构造和析构函数功能

    Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...

  4. C++面试常见问题——10派生类的构造与析构

    派生类的构造与析构 派生类的构造 派生时构造函数与析构函数不会被继承,需要重新定义派生类的构造函数与析构函数.派生类对象包含了基类对象的值,创建派生类时首先会调用基类的构造函数,若派生类中含有其它类对 ...

  5. C++学习笔记 构造&析构 友元 new&delete

    构造&析构函数 构造函数 定义:与类同名,可以有参可以无参,主要功能用于在类的对象创建时定义初始化的状态,无返回值,也不能用void修饰,构造函数不能被直接调用,必须通过new运算符在创建对象 ...

  6. Effective C++笔记:构造/析构/赋值运算

    条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函 ...

  7. 从汇编看c++中含有虚基类对象的析构

    c++中,当继承结构中含有虚基类时,在构造对象时编译器会通过将一个标志位置1(表示调用虚基类构造函数),或者置0(表示不调用虚基类构造函数)来防止重复构造虚基类子对象.如下图菱形结构所示: 当构造类B ...

  8. Effective C++ ——构造/析构/赋值运算符

    条款五:了解C++默认编写并调用那些函数 是否存在空的类? 假设定义类为class Empty{}:当C++编译器处理过后会变成如下的形式: class Empty{ Empty(){} ~Empty ...

  9. EffectiveC++ 第2章 构造/析构/赋值运算

    我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 2 构造 / 析构 / 赋值 条款 05:了解C++ ...

  10. 构造&析构

    构造&析构函数 构造函数 定义:与类同名,可以有参可以无参,主要功能用于在类的对象创建时定义初始化的状态,无返回值,也不能用void修饰,构造函数不能被直接调用,必须通过new运算符在创建对象 ...

随机推荐

  1. POJ2965 The Pilots Brothers' refrigerator (精妙方法秒杀DFS BFS)

    这道题和算法进阶指南的一道题解法一样,必须另操作为奇数.见证明过程 证明:要使一个为'+'的符号变为'-',必须其相应的行和列的操作数为奇数;可以证明,如果'+'位置对应的行和列上每一个位置都进行一次 ...

  2. P1525 关押罪犯 (并查集 / 二分图)| 二分图伪码

    原题链接:https://www.luogu.com.cn/problem/P1525 题目概括: 给你m对关系,每对关系分别涉及到x,y两人,矛盾值为w 请你判断分配x和y到两个集合中,能否避免冲突 ...

  3. L1-048 矩阵A乘以B (15分)

    给定两个矩阵A和B,要求你计算它们的乘积矩阵 \(AB\).需要注意的是,只有规模匹配的矩阵才可以相乘.即若A有 \(R_a\) 行.\(C_a\) 列,B有 \(R_b\) 行.\(C_b\) 列, ...

  4. L3-002 特殊堆栈 (双数组模拟栈)

    堆栈是一种经典的后进先出的线性结构,相关的操作主要有"入栈"(在堆栈顶插入一个元素)和"出栈"(将栈顶元素返回并从堆栈中删除).本题要求你实现另一个附加的操作: ...

  5. Codeforces Round #706 Editorial

    1496A. Split it! 类回文判断,只要 k = 0 或者 \(s[1,k] 和 s[n - k + 1,n]\)是回文即可 特判情况 n < 2 * k + 1 为 NO int m ...

  6. 如何一键私有化部署 Laf ?

    太长不看:Laf 上架了 Sealos 的模板市场,通过 Laf 应用模板即可一键部署! Laf 是一个完全开源的项目,除了使用公有云之外,还有大量的用户选择私有化部署 Laf.然而,私有化部署通常伴 ...

  7. eyebeam高级设置

    概述 VOIP测试过程中,经常会用到各种各样的SIP终端,eyebeam是其中最常见的一种. 在eyebeam的配置option中,只有少量的配置选项,有些特殊的设置无法配置. 比如DTMF码的发码形 ...

  8. shell 编程中 awk ,wc ,$0,$1 等 命令的使用总结

    本文为博主原创,转载请注明出处: 1. awk 的常用场景总结 2. wc 常用场景总结 3. $0,$1,$# 的使用总结 4. seq 的使用总结 5. 获取用户输入 read 使用 1. awk ...

  9. AI伴侣下载

    总结 现在网页上很多下载的AI伴侣下载下来都会有些问题或者不能用,如下链接下载的AI伴侣亲测可以使用! (连接后会提示更新,博主没有选择更新,如有需要也可以更新) https://mit-ai2-co ...

  10. Blazor SSR/WASM IDS/OIDC 单点登录授权实例5 - Winform 端授权

    目录: OpenID 与 OAuth2 基础知识 Blazor wasm Google 登录 Blazor wasm Gitee 码云登录 Blazor SSR/WASM IDS/OIDC 单点登录授 ...