【C++】类和对象1.0

本鼠浅浅介绍一些C++类和对象的知识,希望能得到读者老爷们的垂阅!

目录

1.面向过程和面向对象

2.类的引入

3.类的定义

4.类的访问限定符及封装

4.1.类的访问限定符

4.2.封装

5.C++中struct和class的区别

6.类域

7.类的实例化

8.类对象模型

8.1.类对象大小

8.2.类对象的存储方式

9.this指针 

9.1.this指针的引出

 9.2.this指针的特性

10.Question


1.面向过程和面向对象

作为了解:

C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。 

C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完 成。

没了,介绍完了。其实对于解决问题,C语言关注的是解决问题的动作,而C++关注的是解决问题的对象呗。

2.类的引入

俺们都知道C语言中有结构体的概念。那么C++兼容C语言的大部分语法,所以C++也可以使用结构体。但是C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数

举个栗子给老爷们瞅瞅:

#include<iostream>
#include<assert.h>
using namespace std;
typedef int SLTDateType;
struct SListNode
{SLTDateType data;struct SListNode* next;//动态申请一个节点SListNode* BuyNode(SLTDateType x){SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->data = x;newnode->next = NULL;return newnode;}//单链表打印void Print(SListNode* plist){SListNode* cur = plist;while (cur != NULL){cout << cur->data << "->";cur = cur->next;}cout << "nullptr" << endl;}//单链表尾插void PushBack(SListNode** pplist, SLTDateType x){assert(pplist);if (*pplist == NULL)//单链表为空{*pplist = BuyNode(x);}else//单链表不为空{SListNode* tail = *pplist;while (tail->next != NULL)//找尾{tail = tail->next;}SListNode* newnode = BuyNode(x);tail->next = newnode;}}//单链表头插void PushFront(SListNode** pplist, SLTDateType x){assert(pplist);SListNode* newnode = BuyNode(x);newnode->next = *pplist;*pplist = newnode;}//销毁单链表void Destroy(SListNode** pphead){assert(pphead);SListNode* cur = *pphead;while (cur){SListNode* next = cur->next;free(cur);cur = next;}*pphead = NULL;}
};
int main()
{SListNode* sl = nullptr;sl->PushBack(&sl, 0);sl->PushFront(&sl, -1);sl->Print(sl);sl->Destroy(&sl);return 0;
}

 是可以运行的,且结果符合预期!!

上面结构体的定义,在C++中更喜欢用class来代替struct。这样C++中结构体就升级成了

3.类的定义


类的定义格式:class为定义类的关键字,ClassName为类的名字(可随意变换),{}中为类的主体,注意类定义结束时后面分号不能省略。

这样子:

class className//className是类的名字
{// 类体:由成员函数和成员变量组成};  // 一定要注意后面的分号

类体中内容称为类的成员:类中的变量称为类的属性成员变量; 类中的函数称为类的方法或者成员函数。 


类的两种定义方式:

1.方式一:声明和定义全部放在类体中。

需注意:成员函数如果在类中定义,编译器可能会将其当成内 联函数处理。

像这样子:

class person
{//成员变量的声明int age;const char* name;const char* sex;//成员函数的定义void showinformation(){cout << name << '-' << sex << '-' << age << endl;}
};

 2.方式二:类声明放在.h文件中,成员函数定义放在.cpp文件中。其实就是成员函数声明和定义分离。

注意:成员函数名前需要加类名::

像这样子:

类的.h文件(假如头文件为Person.h):

class person
{//成员变量的声明int age;const char* name;const char* sex;//成员函数的声明void showinformation();
};

类的.cpp文件:

#include"Person.h"//成员函数的定义void person::showinformation(){cout << name << '-' << sex << '-' << age << endl;}

一般情况下,更期望采用第二种方式。

4.类的访问限定符及封装

4.1.类的访问限定符

C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善(咱们看类可以有成员变量和成员函数,分别对应属性与方法)。通过访问权限选择性的将其接口提供给外部的用户使用。

类的访问限定符有三种:public(公有)、protected(保护)、private(私有)

类的访问限定符体现了访问权限

  • public修饰的成员在类外可以直接被访问。
  • protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)。
  • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。
  • 如果后面没有访问限定符,作用域就到 } 即类结束。
  • class的默认访问权限为private,struct为public(因为struct要兼容C)。

注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。


举一些栗子来证实访问限定符的作用:

#include<iostream>
using namespace std;
class person
{int _age;const char* _name;const char* _sex;void showinformation(){cout << _name << '-'<<_sex <<'-'<< _age << endl;}
};
int main()
{person HD;HD._age = 20;//error C2248: “person::_age”: 无法访问 private 成员(在“person”类中声明)return 0;
}

主函数第二条语句编译不通过是因为: class的默认访问权限为private,private修饰的成员在类外不能直接被访问。

如果我们改用public修饰该类的所有成员:

#include<iostream>
using namespace std;
class person
{
public:int _age;const char* _name;const char* _sex;void showinformation(){cout << _name << '-'<<_sex <<'-'<< _age << endl;}
};
int main()
{person HD;HD._age = 20;HD._name = "HD";HD._sex = "male";HD.showinformation();return 0;
}

 编译通过,运行成功!

又如果:

#include<iostream>
using namespace std;
class person
{
public:int _age;const char* _name;const char* _sex;
private:void showinformation(){cout << _name << '-'<<_sex <<'-'<< _age << endl;}
};
int main()
{person HD;HD._age = 20;HD._name = "HD";HD._sex = "male";HD.showinformation();//error C2248: “person::showinformation”: 无法访问 private 成员(在“person”类中声明)return 0;
}

 主函数第五条语句编译报错。因为:该类的成员函数被private修饰。第二条到第四条语句编译通过是因为该类的所有成员变量被public修饰。(访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。)

4.2.封装

面向对象的三大特性:封装继承多态

封装:封装本质是一种管控。将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来 隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。

5.C++中struct和class的区别

C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来定义类,和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类 默认访问权限是private。在继承和模板参数列表位置,struct和class也有区别,本鼠以后再介绍,因为本鼠也不清楚捏!

6.类域

类定义了一个新的作用域:类域,类的所有成员都在类的作用域中。与命名空间域一样,类域也只会影响访问,所以在类体外定义成员时,需要使用 :: 作用域限定符指明成员属于哪个类域。

举例请看类的定义方式二。

其实类的定义方式二中的成员函数的声明和定义分离写到同一个.cpp文件下面也行,像这样子:

#include<iostream>
using namespace std;
class person
{
public:int _age;const char* _name;const char* _sex;void showinformation();
};
void person::showinformation()
{cout << _name << '-' << _sex << '-' << _age << endl;
}
int main()
{person HD;HD._age = 20;HD._name = "HD";HD._sex = "male";HD.showinformation();return 0;
}

 编译也通过,运行成功。

不过既然都写到同一个文件下了,成员函数的声明和定义分开写好像有种脱裤子放屁的无力感,没必要啊。。。 直接写成类的定义方式一不就好了。。。

7.类的实例化

类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它。所以要让类有使用价值就要将类实例化。

用类类型创建对象的过程,称为类的实例化。说白了类的实例化就是创建类型为该类的对象呗。像这样子:

#include<iostream>
using namespace std;
class person
{
public:int _age;const char* _name;const char* _sex;void showinformation();
};
void person::showinformation()
{cout << _name << '-' << _sex << '-' << _age << endl;
}
int main()
{person HD;//HD是person类实例化的对象return 0;
}

 定义出一个类并没有分配实际的内存空间来存储它,如上代码定义出person类,但是没有给person类开空间的。用person类类型创建对象HD,就是person类实例化,对象HD是开了空间来存储的。

一个类可以实例化出多个对象,很简单易懂吧,就像这样:

#include<iostream>
using namespace std;
class person
{
public:int _age;const char* _name;const char* _sex;void showinformation();
};
void person::showinformation()
{cout << _name << '-' << _sex << '-' << _age << endl;
}
int main()
{person HD;//HD是person类实例化的对象person LCD;//LCD也是person类实例化的对象return 0;
}

HD和LCD都是person类实例化对象 。

实例化出的对象占用实际的物理空间,存储类成员变量,我们看:

#include<iostream>
using namespace std;
class person
{
public:int _age;const char* _name;const char* _sex;void showinformation();
};
void person::showinformation()
{cout << _name << '-' << _sex << '-' << _age << endl;
}
int main()
{person._age = 10;//error C2059: 语法错误:“.”return 0;
}

编译报错是因为:person类是没有空间的,只有person类实例化出的对象才有具体的年龄。person类中的成员变量(如_age)只是声明,没有开空间来存储成员变量,只有person类实例化对象才有空间存储类成员变量(如_age)。

最后提一嘴:类对象实例化的时候代码可以带上class或者struct,也可以不带,一般不会带上。比如这样子写也能编译通过,运行成功:

#include<iostream>
using namespace std;
class person
{
public:int _age;const char* _name;const char* _sex;void showinformation(){cout << _name << '-' << _sex << '-' << _age << endl;}
};
int main()
{class person HD;HD._age = 20;HD._name = "HD";HD._sex = "male";HD.showinformation();return 0;
}

 

8.类对象模型

8.1.类对象大小

我们也许会有疑问:C语言的结构体成员可不能有函数,计算结构体变量的大小遵循结构体内存对齐呗。但是类定义时可以包含成员变量和成员函数,那么类实例化对象的大小(占多少字节)该如何计算捏?

答案就是一个类实例化对象的大小(或者说类的大小),实际就是该类中”成员变量”之和,当然要注意内存对齐。就是说不用管类成员函数的存在。为什么这样子,本鼠下边再解释。

#include<iostream>
using namespace std;
class rectangle
{
public:double _long;double _wide;double _high;void showinformation(){cout << _long << '-' << _wide << '-' << _high << endl;}
};
int main()
{rectangle n1;cout << sizeof(rectangle) << endl;cout << sizeof(n1);return 0;
}

 

 额,sizeof(类)和sizeof(类实例化对象)是同一个意思,都是计算类实例化对象多大。

附上结构体内存对齐规则:

  • 1. 第一个成员在与结构体偏移量为0的地址处。
  • 2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的对齐数为8
  • 3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
  • 4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。如果空类的大小为0个字节,那么该类实例化对象如何证明存在过捏?

#include<iostream>
using namespace std;
class N
{
};
int main()
{N n1;cout << sizeof(N) << endl;cout << sizeof(n1);return 0;
}

 

 好了,为啥子一个类实例化对象的大小(或者说类的大小),实际就是该类中”成员变量”之和,当然要注意内存对齐。就是说不用管类成员函数的存在。请看类对象的存储方式!!

8.2.类对象的存储方式

拿这个代码来说:

#include<iostream>
using namespace std;
class person
{
public:int _age;const char* _name;const char* _sex;void showinformation(){cout << _name << '-' << _sex << '-' << _age << endl;}
};
int main()
{class person HD;person LCD;return 0;
}

person类实例化对象有两个:HD和LCD。这两个对象个中成员变量是不同的(需要存储不同的属性,所以说是不同的),但是调用同一份函数(类方法是一样的)。当一 个类创建多个对象时,如果每个对象中都会保存一份代码,相同代码保存多次,浪费空间。 

那么计算机的做法是:当一个类创建多个对象时,对象只保存成员变量,成员函数存放在公共代码段(区)。

就是说当类实例化对象时,只会给该对象开遵循结构体内存对齐的“成员变量”之和的内存空间,当该对象需要用到成员函数时去公共代码段调用。

9.this指针 

9.1.this指针的引出

看一个代码:

#include<iostream>
using namespace std;
class Date
{int _year; // 年int _month;// 月int _day;// 日
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
};
int main()
{Date d1, d2;d1.Init(2024, 6, 4);d2.Init(2003, 12, 12);d1.Print();d2.Print();return 0;
}

 

运行没毛病,但是有一个问题: 

 Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分。那当d1调用 Init 函 数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?

C++中通过引入this指针解决该问题,其实即:C++编译器给每个“非静态的成员函数“增加了一个隐藏 的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量” 的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。this指针是每个“非静态的成员函数”的第一个参数,而且是隐藏起来的。

this指针是隐藏起来的,拿上面代码来说:当d1调用Init函数时,传递的实参不仅仅有明面上的2024、6和4,还有该对象的地址,即d1的地址,而且第一个传递d1的地址。

Init函数有一个隐藏的this指针用来接收d1的地址,所以Init函数知道该设置d1对象而不是d2对象。

 9.2.this指针的特性

用本代码举例:

#include<iostream>
using namespace std;
class Date
{int _year; // 年int _month;// 月int _day;// 日
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
};
int main()
{Date d1, d2;d1.Init(2024, 6, 4);d2.Init(2003, 12, 12);d1.Print();d2.Print();return 0;
}
  • this指针的类型:类类型* const。即成员函数中,不能给this指针赋值。比如上面代码Init函数隐藏的this指针类型是Data* const。
  • 在实参或者形参的位置上不能将this指针显示写,但是函数内部可以使用。

请看:

#include<iostream>
using namespace std;
class Date
{int _year; // 年int _month;// 月int _day;// 日
public:void Init(Date const* this, int year, int month, int day){_year = year;_month = month;_day = day;}void Print(Data const*this){cout << _year << "-" << _month << "-" << _day << endl;}
};
int main()
{Date d1, d2;d1.Init(&d1, 2024, 6, 4);d2.Init(&d2, 2003, 12, 12);d1.Print(&d1);d2.Print(&d2);return 0;
}

编译报错!因为将形参位置隐藏的this指针显示写出来了,而且实参位置传入d1地址或者d2地址给this指针。这些都是编译器完成的,我们不应该显示写出来。

再看:

#include<iostream>
using namespace std;
class Date
{int _year; // 年int _month;// 月int _day;// 日
public:void Init( int year, int month, int day){this->_year = year;this->_month = month;this->_day = day;}void Print(){cout << this->_year << "-" << this->_month << "-" <<this-> _day << endl;}
};
int main()
{Date d1, d2;d1.Init( 2024, 6, 4);d2.Init( 2003, 12, 12);d1.Print();d2.Print();return 0;
}

编译通过,运行成功!函数内部可以使用隐藏的this指针。详情请看Init函数或者Print函数内部。

  • this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。 
  • this指针是“成员函数”第一个隐藏的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。

呃呃呃:this指针存储在栈区(有些编译器用寄存器存储),因为它是一个形参。

10.Question

1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

#include<iostream>
using namespace std;
class A
{
public:void Print(){cout << "Print()" << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->Print();return 0;
}

也许你会跟本鼠一样,看到空指针就想选A。但是正确答案是C。因为p虽然是空指针,但是Print函数并不是通过解引用p找到的,因为Print函数存储在公共代码段中,而不是存储在p指向的空间里。

 看看结果如图:

 2.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

class A
{ 
public:void PrintA() {cout<<_a<<endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->PrintA();return 0;
}

哈哈哈,答案选B。因为PrintA函数会将地址p作为实参传递给PrintA函数隐藏的形参this指针。我们看PrintA函数内部需要用到this指针解引用的哦,this指针接收到的值是空指针,而且成员变量_a是存储在this指向的空间里面的(成员变量存储在类实例化对象里面),当然会崩溃了。

崩溃了!!

感谢阅读!!!!!!! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/21775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线性代数|机器学习-P5特征值和特征向量

文章目录 1. 特征值和特征向量1.1 特征向量1.2 向量分解 2. 矩阵相似2.1 特征值求解法-相似2.2 特殊特征值2.3 反对称矩阵 3.对称矩阵 1. 特征值和特征向量 1.1 特征向量 假设有一个n行n列的方阵A&#xff0c;有 n 个不相同的特征值为 λ \lambda λ,特征向量为 x 1 , x 2 , …

(2022,扩散模型,评分函数,数据流形的内在维度,SVD)使用扩散模型估计数据流形的维度

Your diffusion model secretly knows the dimension of the data manifold 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 引言 2. 相关工作 3. 背景&#xff1a;基于评…

【YOLOv5/v7改进系列】引入Slimneck-GSConv

一、导言 GSConv旨在平衡模型的准确度与速度&#xff0c;针对自动驾驶车辆中目标检测任务设计。从类脑研究中得到的直观理解是&#xff0c;具有更多神经元的模型能够获得更强的非线性表达能力。但是&#xff0c;不容忽视的是生物大脑处理信息的强大能力和低能耗远远超过计算机…

二、Nginx目录结构与基本运行原理

目录 一、目录结构 二、运行原理 一、目录结构 我们使用tree 命令查看nginx的目录。如果tree 命令失效&#xff0c;需要安装tree工具 [rootlocalhost local]# yum install -y tree[rootlocalhost /]# tree /usr/local/nginx /usr/local/nginx ├── client_body_temp # PO…

C语言 | Leetcode C语言题解之第129题求根节点到叶节点数字之和

题目&#xff1a; 题解&#xff1a; int sumNumbers(struct TreeNode* root) {if (root NULL) {return 0;}int sum 0;struct TreeNode* nodeQueue[2000];int numQueue[2000];int leftQueue 0, rightQueue 0;nodeQueue[rightQueue] root;numQueue[rightQueue] root->v…

Vue——初识组件

文章目录 前言页面的构成何为组件编写组件组件嵌套注册 效果展示 前言 在官方文档中&#xff0c;对组件的知识点做了一个很全面的说明。本篇博客主要写一个自己的案例讲解。 vue 官方文档 组件基础 页面的构成 说到组件之前&#xff0c;先大致说明下vue中页面的构成要素。 在…

手写数据集minist基于pytorch分类学习

1.Mnist数据集介绍 1.1 基本介绍 Mnist数据集可以算是学习深度学习最常用到的了。这个数据集包含70000张手写数字图片&#xff0c;分别是60000张训练图片和10000张测试图片&#xff0c;训练集由来自250个不同人手写的数字构成&#xff0c;一般来自高中生&#xff0c;一半来自工…

MTU相关随笔

一、MTU的概念 MTU&#xff08;最大传输单元&#xff09;&#xff1a;用来通知对方所能接受数据服务单元的最大尺寸&#xff0c;说明发送方能够接受的有效载荷大小。MTU是包或帧的最大长度&#xff0c;一般以字节记&#xff0c;如果过大在碰到路由器时会被拒绝转发&#xff0c…

SpringBoot项目本地运行正常,jar包运行时前端报错403:No mapping for......

SpringBoot项目本地运行正常&#xff0c;jar包运行时前端报错403&#xff1a;No mapping for… 提示&#xff1a;在部署jar包到云服务器上之前&#xff0c;一定要在本地运行jar包&#xff0c;查看前端代码是否运行正常&#xff0c;若报错的话可以节省很多时间 方式&#xff1a;…

友顺科技(UTC)分立器件与集成IC产品选型和应用

友顺科技股份有限公司成立于1990年&#xff0c;是全球领先的集成电路与功率半导体厂商 ,集团总部位于台北&#xff0c;生产基地位于福州、厦门。 友顺科技具有完整模拟组件产品线&#xff0c;其中类比IC涵盖各种稳压器、PWM控制IC, 放大器、比较器、逻辑IC、Voltage Translato…

基于飞腾 D2000 8 核+ 32G DDR+板载 6 千兆电口+ 4 千兆光口高性能网络安全主板

第一章、产品介绍 1.1 产品概述 XM-D2000GW是一款基于飞腾 D2000 8 核X100 桥片高性能网络安全主板&#xff0c;D2000 为飞腾首款支持 8 核桌面平 台处理器&#xff0c;支持双通道 DDR4-2666 内存&#xff0c;芯片内置国密 SM2/SM3/SM4/SM9 加速引擎&#xff0c;支持单精度、双…

gitee和github的协同

假设gitee上zhaodezan有一个开发库&#xff0c;但是从andeyeluguo上拉取最新的&#xff08;从github上同步过来最新的&#xff09; git remote add dbgpt_in_gitee https://gitee.com/andeyeluguo/DB-GPT.git remote -v git pull --rebase dbgpt_in_gitee main 有冲突可能需要…

【调试笔记-20240603-Linux-在 OpenWrt-23.05 上运行 ipkg-build 生成. ipk 安装包】

调试笔记-系列文章目录 调试笔记-20240603-Linux-在 OpenWrt-23.05 上运行 ipkg-build 生成. ipk 安装包 文章目录 调试笔记-系列文章目录调试笔记-20240603-Linux-在 OpenWrt-23.05 上运行 ipkg-build 生成. ipk 安装包 前言一、调试环境操作系统&#xff1a;Windows 10 专业…

Android11 AudioTrack和Track建立联系

应用程序创建AudioTrack时&#xff0c;导致AudioFlinger在播放线程中&#xff0c;创建Track和其对应。那它们之间是通过什么来建立联系传递数据的&#xff1f;答案是共享内存。 创建Track时&#xff0c;导致其父类TrackBase的构造函数被调用 //frameworks/av/services/audiofl…

数字化时代还需要传统智慧图书馆吗

尽管以电子阅览室代表的数字化时代带来了许多便利和创新&#xff0c;但传统智慧图书馆依然具有重要的价值和意义。以下是一些原因&#xff1a; 1. 保存历史文化&#xff1a;传统智慧图书馆是保存历史文化遗产的重要载体&#xff0c;收藏了许多珍贵的古籍、手稿和纸质图书&#…

基于 Amazon EC2 快速部署 Stable Diffusion WebUI + chilloutmax 模型

自2023年以来&#xff0c;AI绘图已经从兴趣娱乐逐渐步入实际应用&#xff0c;在众多的模型中&#xff0c;作为闪耀的一颗明星&#xff0c;Stable diffusion已经成为当前最多人使用且效果最好的开源AI绘图软件之一。Stable Diffusion Web UI 是由AUTOMATIC1111 开发的基于 Stabl…

vue-cl-service不同环境运行/build配置

概述 在项目开发过程中&#xff0c;同一个项目在开发、测试、灰度、生产可能需要不同的配置信息&#xff0c;所以如果能根据环境的不同来设置参数很重要。 vue项目的vue-cl-service插件也支持不同环境的不同参数配置和打包。 实现 新建不同环境配置文件 vue项目中的配置文件以…

面向对象程序设计之从C到C++的初步了解

1. C语言 1. C的发展 C是从C语言发展演变而来的&#xff0c;首先是一个更好的C引入了类的机制&#xff0c;最初的C被称为“带类的C”1983年正式取名为C 从1989年开始C语言的标准化工作 于1994年制定了ANSIC标准草案 于1998年11月被国际标准化组织(ISO)批准为国际标准&#xf…

Ubuntu系统安装

目录 安装准备 安装步骤 虚拟机配置 系统安装 安装准备 Ubuntu系统镜像&#xff0c;虚拟机环境 虚拟机环境 使用的虚拟机软件为VMware Workstation 系统镜像 阿里镜像站&#xff1a;阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 (aliyun.com)https://developer.aliyun.com…

记一次使用mysql存储过程时,游标取值为空问题

call modify_collation(num,count_num) > 1146 - Table test.table_name doesnt exist > 时间: 0.009s 我在使用mysql存储过程时&#xff0c;打印时游标取值为空&#xff0c;报错找不到表。我的过程语句是这样的&#xff1a; drop procedure if exists modify_collation…