C和C++的NULL
C头文件说明了空指针的二义性
#undef NULL #if defined (___cplusplus) #define NULL 0 #else #define NULL((void *)0) #endif
字面常量0的类型既可以是一个整型,也可以是一个无类型指针(void * ) 。C++11标准用nullptr 解决二义性问题
typedef decltype(nullptr) nullptr_t;
例子1
using namespace std;
void func(char* p) {}
void func(int x) {}
int main()
{
func(NULL);//0
return 0;
}
例子2
int a =NULL; //a 的值是0了。 int b= nullptr ; //报错 char *p=nullptr; if(p==NULL)//c++不要这样写 if(p==nullptr)
注意: 1、nullptr 是C11新引入的关键字,是一个所谓"指针空值类型"的常量,在C++程序中直接使用。 2、在C11 中 , sizeof(nullptr) 与 sizeof((void*)0) 所占的字节数相同都( 4,或 8)。
2、为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。
typedef:合法变量的定义变成类型 的定义
结构体名和结构体类型名在C和C++上的区别
using
typedef int Array[10]; //typedef double Array[20]; //typedef double Array[100]; using iArray =int[10]; using cArray =char[10];
我们可以看见,用typedef无法把权利交给用户。
怎么把权利给用户更灵活呢?请看如下代码:
templateusing Array=T[N]; int main() { Array ar; Array br; }
通过模板 ,我们可以在主函数中自定义想要的类型和大小,非常方便。
当然我们也可以把模板初始化一下:
templateusing Array=T[N]; int main() { Array //用类型名定义一个函数指针 using pfun=int(*)(int ,int);函数名的给法:
1.int add(int,int)函数的声明
2.int add(int a,int b)
{} //函数的定义
3.编译连接之后,或运行时标识名被地址替代!!!
4.add(12,23)加括号代表要 调动函数
5.函数名后没有括号代表着函数的地址。int (*pfun)(int,int)=add;C++字符串替代字符数组
using namespace; int main() char stra[]={"hello"}; int n=strlen(stra); for(int i=0;iif(stra[i]) { } } strcat(stra,"hello");//str7个字节,再链接就越界了。所以字符数组存放字符串不方便 下面代码通过string 关键字使得字符串操作更加灵活
#include//std::string s1="tulun"; string s1 ="tulun"; // 字符串 //string 字符串类型 // s1.length(); // s1.size(); int n=s1.size(); for(int i = 0;i cout< >s1; // new data // 空格为中止符 cout< string stra=“123”;
string strb=“helo”;
//stra+strb 链接
stra= stra+“hello”+strb;int main() { string s1 = "tulun"; // 字符串 //string 字符串类型 string s2 = "123"; const char* p = s2.data();//把s2地址给p; cout << s2.data() << endl;//cout << *(s2.data()*) << endl; 结果打印不出来 ?? const char* cp = s2.c_str(); return 0; }回去找到C++接口函数
实例:从以下程序看C++中的sizeof()
int main() { std::string stra; typedef struct Test { char* p; }*Test1; Test arr; cout << "sizeof(arr):" << sizeof(arr) << endl; arr.p = (char*)malloc(18); cout << "sizeof(arr):" << sizeof(arr) << endl; strcpy(arr.p, "hellooooooo"); cout << "sizeof(arr):" << sizeof(arr) << endl; //cout << stra.length() << endl; }在C++中,sizeof(str)的大小不是str中存放字符总数的大小 而是str空间的大小。
int main() { std::string stra; for(int i=0;i<20;++i) { cout<<"sizeof(stra):"<面向对象的编程
1.理解面向对象的编程
3.类型设计与实例化对象封装(Encapsulation)是面向对象程序设计最基本的特性,把数据(属性)和函数(操作)合成
一个整体,这在计算机世界中是用类与对象实现的。class 类型名称 { public: 成员列表1; protected: 成员列表2; private: 成员列表3; };//最后的分号不可少;注意:所有说明都有分号访问限定符(access specifier)有三种: public (公共的), private (私有的)和
protected(保护的)。第一种说明的类型所产生的的实体成员能从外部进行访问,另外两种说明的类型所产生的的实体(对象)成员不能从外部进行访问。每种说明符可在类体中使用多次。它们的作用域是从该说明符出现开始到下一个说明符之前或类体
结束之前结束。如果在类体起始点无访问说明符,系统默认定义为私有( private )。访问说明符 private (私有 的)和 protected
(保护的)体现了类具有封装性(Encapsulation)。STRUCT结构体属性的可访问性默认是公有的,而类的可访问性默认是私有的
属性设计成私有 ,方法设计成公有。
属性设计成公有,对象失去 了封装特性。成员函数
类型设计的更关键部分是对数据成员的操作,用函数来完成:
public://可以在类中定义函数,系统默认为INLINE函数
class CGoods { private: char Name[21]; int Amount; float Price; float Total_value; public://可以在类中定义函数,系统默认为INLINE函数 void RegisterGoods(char [], int,float); //输入数据 // inine void RegisterGoods(char [], int,float); //可以加inline void CountTotal(void); //计算商品总价值 void GetName(char[]); //读取商品名 int GetAmount(void); //读取商品数量 float GetPrice(void); //读取商品单价 float GetTotal_value(void); //读取商品总价值 };void CGoods::RegisterGoods(const char*,int,float)//可以在类外定义,但要署名在CGoods 内 { }对象的创建与使用
对象是类的实例(instance)。声明一种数据类型只是告诉编译系统该数据类型的构造,并没有预定内存。类只是一个样板(图纸),以此样板可以在内存中开辟出同样结构的实例–对象。 创建类的对象可以有两种常用方法。
int a;//内置类型定义变量 CGoods Car; //类型 创建了一个对象。int main() { CGoods tea;//开始定义对象。设计了一个tea的类型,还不是对象,因为还没开辟内存(实体), CGoods book; tea.RegisterGoods("black_tea", 12, 560); tea.CountTotal(); book.RegisterGoods("Thinking In C++", 20, 128); book.CountTotal(); return 0; }CGoods tea 这条语句,之后调动构造函数才是真的创建了对象
注意: 创建若干个对象 操作公有成员 。一个公共代码区 this指针的根本目的是节省空间 ,方法是用list指针指向对象。
this指针
C++对象模型讨论:
方案一:各对象完全独立地安排内存的方案
方案二:各对象的代码区共用的方案:
我们当然要选用第二种方案.
创建对象过程中编译器的动作
1、对数据成员(属性)进行扫描(描述表)
2、识别成员函数 (函数的声明)
3、改写类函数 ,用this指针指向对象(形参表加入this指针,函数代码中的每个属性前加this)
为什么给this指针而不是引用呢
(自己理解:因为引用的本质就是指针。)构造函数和析构函数
数据成员多为私有的,要对它们进行初始化,必须用一个公有函数来进行。同时这个函数应该在且
仅在定义对象时自动执行一次。称为构造函数(constructor) 。
构造函数用途:1)创建对象,2)初始化对象中的属性,3)类型转换。有对象一定要有空间,有空间不一定有对象
构造函数的定义与使用
构造函数是特殊的公有成员函数(在特殊用途中构造函数的访问限定可以定义成私有或保护),其
特征如下:
1.函数名与类名相同。
2.构造函数无函数返回类型说明。注意是没有而不是void,即什么也不写,也不可写void。实际上
构造函数有返回值,返回的就是构造函数所创建的对象。
3.在程序运行时,当新的对象被建立,该对象所属的类构造函数自动被调用,在该对象生存期中也
只调用这一次。
4.构造函数可以重载。严格地讲,类中可以定义多个构造函数,它们由不同的参数表区分,系统在
自动调用时按一般函数重载的规则选一个执行。
5.构造函数可以在类中定义,也可以在类中声明,在类外定义。
6.如果类说明中没有给出构造函数,则C++编译器自动给出一个缺省的构造函数:
类名(void) { }
但只要我们定义了一个构造函数,系统就不会自动生成缺省的构造函数。只要构造函数是无参的或
者只要各参数均有缺省值的,C++编译器都认为是缺省的构造函数,并且缺省的构造函数只能有一个 。
圈1:1个字符的占位符
调动构造函数才是真的创建了对象C语言 有空间就能操作
C++ 有空间,在创建对象后 才能操作(有对象一定要有空间)
using namespace; Complex
初始化 :先天Compex(int r,int i) :Real{},Image{}//初始化赋值:后天
int main () { CDATE cd1; CDate cd2(2024,5,1);
构建顺序是类声明的顺序



