2022 7.14
城南小陌又逢春 ,只见梅花不见人。
输入输出流
输出流cout输入流cin
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int a;
double b;
char s[100];
cin>>a>>b>>s;
cout<<"a="<<a<<"b="<<b<<"s="<<s<<endl;
return 0;
}
构造函数:
普通构造:默认普通构造,没有参数返回值。
拷贝构造:分为浅拷贝,深拷贝
移动构造:编译时需要加入连接-fno-elide-constructors
代码如下
/*===============================================
* 文件名称:constructor.cpp
* 创 建 者:月亮与六便士
* 创建日期:2022年07月14日
* 描 述:
================================================*/
#include <iostream>
#include<cstring>
using namespace std;
class demo{
public:
//重写构造
demo(char *q=nullptr)
{
str=new char[strlen("hello")+1];
strcpy(str,q);
cout<<"succesful x"<<endl;
}
//拷贝构造,深拷贝
demo(const demo &obj)
{
str=new char[strlen(obj.str)+1];
strcpy(str,obj.str);
cout<<"succesful y"<<endl;
}
//移动构造
demo( demo &&obj)
{
str = obj.str;
obj.str=nullptr;
cout<<"succesful z"<<endl;
}
char * getp(void);
void get_addr(void);
char &at(int n);
void set(void);
private:
char *str;
int len;
};
char * demo::getp(void)
{
return str;
}
void demo::get_addr(void)
{
printf("%p\n",str);
}
char & demo::at(int n)
{
if(n>strlen(str)-1)
{
printf("erro\n");
}
//str[n]=str[n];
return str[n];
}
void demo::set(void)
{
char buf[32]={0};
printf("plead input \n");
fgets(buf,sizeof(buf),stdin);
printf("%ld\n",strlen(buf));
if(strlen(buf)>strlen(str))
{
delete str;
str=new char[strlen(buf)+1];
strncpy(str,buf,strlen(buf)-1);
printf("change str:%s \n",str);
}
if(strlen(buf)<strlen(str))
{
strncpy(str,buf,strlen(buf)-1);
printf("change str:%s \n",str);
}
//printf("change str:%s \n",str);
}
int main(int argc, char *argv[])
{
char buf[32]="helloworld";
int n=2;
demo x("hello");
cout<<x.getp()<<endl;
x.get_addr();
puts("----------");
cout<<x.at(2)<<endl;
puts("----------");
x.at(2)='m';
printf("%c\n",x.at(n));
cout<<x.getp()<<endl;
puts("-----------------------\n");
x.set();
puts("-----------------------");
demo y(x);
cout<<y.getp()<<endl;
demo z=buf;
cout<<z.getp()<<endl;
return 0;
}
using namespace <>;
名词空间,把内域变成全局,
2022 7.15
析构函数
对象销毁时自动调用函数,它可以显示调用
~类名(void)
注意:1.当存在移动构造时,需要在释放空间之前判断是否是临时变量
如果时临时变量那么就不释放空间
2.使用析构显示调用时需要注意重复释放的问题
#include <iostream>
#include <cstring>
using namespace std;
class String{
public:
//普通构造
String(const char*p)
{
/*
if(nullptr == p)
异常处理
*/
cout<<"normal"<<endl;
addr = new char[strlen(p)+1]; //开辟空间
strcpy(addr, p);
len = strlen(p);
}
//深拷贝
String(const String & obj)
{
cout<<"cpy"<<endl;
addr = new char[strlen(obj.addr)+1];
strcpy(addr,obj.addr);
len = obj.len;
}
//移动构造
String(String && obj)
{
cout<<"move"<<endl;
addr = obj.addr;
obj.addr = nullptr;
len = obj.len;
}
//析构函数
~String()
{
cout<<"delte"<<endl;
if(addr != nullptr)
{
delete []addr;
addr = nullptr;
}
}
char &at(const int id) //因为需要通过返回值修改成员变量所以使用引用
{
return addr[id];
}
char* get_addr()
{
return addr;
}
void setval(const char* p)
{
if(strlen(p) > len)
{
//p大于原来的空间,应该重新开辟一个空间
delete []addr;
addr = new char[strlen(p)+1];
strcpy(addr, p);
len = strlen(p);
}
else
{
strcpy(addr, p);
len = strlen(p);
}
}
void append(const char* p)
{
char buf[len+1]; //存储原始数据
strcpy(buf, addr);
delete []addr;
addr = new char[len+strlen(p)+1];
strcpy(addr, buf);
strcat(addr, p);
len += strlen(p);
}
private:
char *addr;
int len;
};
void test()
{
char buf[100] = "hello";
String A = buf;
}
int main()
{
test();
while(1);
}
关键字
static
1.修饰变量
1.全局变量,生命周期不变,作用域被限制在本文件
2.局部变量, 延长声明周期到程序结束,作用域不
2.修饰函数
声明周期不变,作用域限制在本文件
3.修饰类相关
特点:静态成员,不和具体对象关联,没有对象生成静态成员也存在
静态成员不属于类,多个对象公用一个静态成员
静态成员使用之前必须初始化 类型+类名::变量名=n;
const
1.const修饰成员变量
1.修饰的变量不能被更改,const修饰的变量需要初始化
2.const修饰的成员变量,必须使用初始化列表进行初始化
3.非const成员函数可以访问,const成员变量
初始化列表
1.可以初始化const修饰的变量,也可以初始化非const修饰的变量
demo(int n, char c , int *p)
:a(n),ch(c),b{p[0], p[1], p[2]}
{}
//初始化列表格式,分别对int,char,数组,进行的初始化
2.const修饰函数
格式: 返回值 函数名()const;
1.const修饰的函数可以访问非const成员
2.const修饰的函数可以访问const成员
3.函数内部不能出现修改成员变量值的逻辑出现
3.const修饰类
const修饰的对象,只能调用对象的const修饰的成员函数
重载运算符
1 "." "::" sizeof "?:" 运算符不能重载,其它的可以重载。
2看运算符的第一个参数,如果是基本类型,必须用友元;
* 运算符重载函数的基本语法:
* 数据类型 operator<运算符>(<形参列表>)
* {
* //函数体
* }
* 注意:
* 1、数据类型 表示该函数返回值的数据类型;
* 2、<运算符> 表示需要重载的运算符(C++ 中除了以下运算符不能被重载,其他都可以:
* sizeof、.点号运算符、?问号表达式、::作用于访问符)
* 3、operator<运算符> :构成函数名
* 4、运算符操作的对象是什么类型,那么运算符重载函数就应该设计在 哪个类。
*
C++模板:
是支持参数多态化的工具。
* 实质:设计一种通用类型的函数或类,在函数或类使用时,让数据成员、成员函数、函数返回值可以是任意类型。
* 目的:让程序员编写与类型无关的代码,是 泛型编程的基础。
* 函数模板: 针对函数参数类型不同的函数。
* 类模板: 针对数据成员、成员函数数据类型、参数类型不同的类。
*
函数模板 :
C++模板:是支持参数多态化的工具。
* 实质:设计一种通用类型的函数或类,在函数或类使用时,让数据成员、成员函数、函数返回值可以是任意类型。
* 目的:让程序员编写与类型无关的代码,是 泛型编程的基础。
*
* 函数模板:
* 针对函数参数类型不同的函数。
* 类模板:
* 针对数据成员、成员函数数据类型、参数类型不同的类。
*
*
* 函数模板语法结构:
* template < <类型模板形参列表> > 类型模板形参 函数名(<形参列表>);
* 注意:
* template:模板说明的关键字
* <类型模板形参列表>:用 class 或 typename 定义的变量,多个模板形参之间以 空格隔开
* 1、class T1: 定义类型模板形参 T1, 用来代替函数的相关数据类型, 简称 模板形参。
* eg:
* template<class T1> T1 add(T1 x, T1 y);
* */
非类型模板参数,只能是int ,指针 ,引用