-
a是int型变量a的地址
(char *)将int型指针(指向4个字节)转换成char型指针(指向一个字节)
char *p声明一个char型指针变回量,答接受转换的地址。
#include <stdio.h>
int main()
{
int i = 0x1122;
char * p = (char *)&i;
if (p[0] == 0x22 && p[1] == 0x11) {
printf("Little Endian\n");
}
else if (p[0] == 0x11 && p[1] == 0x22) {
printf("Big Endian\n");
}
}查看全部 -
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
const int arrLength = 20; // 数组长度
double* getStusGrade()
{
// 学生成绩数组
double gradeArr[arrLength] = {
60.5, 62.5, 67.5, 40, 50, 60, 70, 80, 90, 100,
90.5, 12, 13.5, 84, 65, 76, 87, 88, 99, 20.5
};
// 堆内存上分配160个字节的内存空间 20×8个字节
double* arrP = (double*)malloc(arrLength * sizeof(double));
// 将栈内存上的数组数据添加到堆内存空间中
for (int index = 0; index < arrLength; index++)
{
arrP[index] = gradeArr[index];
}
return arrP;
}
int main(int argc, char** argv)
{
double* ptr = getStusGrade();
// 输出学生成绩
for (int index = 0; index < arrLength; index++)
{
std::cout << "学生" << index + 1 << "的数学成绩是:" << ptr[index] << std::endl;
}
free(ptr);
ptr = nullptr;
return 0;
}
查看全部 -
向函数中传递一个对象:
若是直接在函数的参数列表中传递对象,那么这个传递到函数内部的对象仅仅是副本,造成资源浪费。
所以,一般选择使用指针或者引用作为函数列表中的对象引用
使用指针作为函数列表的参数时,为了增加健壮性还需要对指针进行判空操作。
因此可以选择使用引用传递对象
而且,可以使用const修饰来增加对象的存在周期,且指向不可修改。
查看全部 -
将父类的析构函数声明为虚函数,作用是用父类的指针删除一个派生类对象时,派生类对象的析构函数会被调用。例如:
class Staff
{
public:
std::string name;
int age;
virtual ~Staff()
{
}
}
class Coder : public Staff
{
public:
std::string language;
virtual ~Coder()
{
}
};
int main(int argc,char **argv)
{
Staff * s = new Coder();
delete s;
return 0;
}此时如果析构函数不加 virtual,那么 delete 父类指针的时候,子类的析构就不会被调用,某些情况下会导致内存泄漏。
查看全部 -
计算机硬件有两种储存数据的方式:大端字节序(big endian)和小端字节序(little endian)。
我们现在有一个整数514:。用16进制表示是0x0202,然后我们吧这个整数拆分成两个字节,第一个字节为0000 0010,第二个字节为0000 0010。
现在大部分的机器,都采用了小端字节序。但是在IO方面,则大部分使用大端字节序。例如:你要使用网络发送一个int类型的变量,要先把int转换成大端字节序,然后通过网络发送。
大端字节序又被称之为网络细节序。
查看全部 -
test
查看全部 -
面向过程的结构化编程:把数据放入到动作当中。采用自顶向下的方法构建程序,包含顺序,选择和循环三种结构。按照程序执行的时序步骤来完成。
类由成员函数和成员变量组成,可以通过实例化,得出很多的对象。
查看全部 -
运算符重载
RMB.h
class RMB { public: RMB(int _yuan, int _jiao, int _fen); ~RMB(); private: int yuan = 0; int jiao = 0; int fen = 0; };
RMB.cpp
#include "RMB.h" RMB::RMB(int _yuan, int _jiao, int _fen) { yuan = _yuan; jiao = _jiao; fen = _fen; } RMB::~RMB() { }
为这个类写了些必要的部分之后,我们要完成一个功能,加法功能,1块9毛加2块3毛,用程序应该怎么写呢?我们可以添加一个 Add 函数,如下:
RMB.h
class RMB { public: RMB(int _yuan, int _jiao, int _fen); ~RMB(); RMB Add(const RMB & rmb); private: int yuan = 0; int jiao = 0; int fen = 0; };
RMB.cpp
#include "RMB.h" RMB::RMB(int _yuan, int _jiao, int _fen) { yuan = _yuan; jiao = _jiao; fen = _fen; } RMB::~RMB() { } RMB RMB::Add(const RMB & rmb) { RMB rmbRes(0, 0, 0); // 分 int f = rmb.fen + fen; int f_ = f / 10; rmbRes.fen = f % 10; // 角 int j = rmb.jiao + jiao + f_; int j_ = j / 10; rmbRes.jiao = j % 10; // 元 int y = rmb.yuan + yuan + j_; int y_ = y / 10; rmbRes.yuan = y % 10; return rmbRes; }
这样,我们就实现了一个 Add 函数,如果想要把两个人民币加起来,就可以这样用:
int main(int argc,char **argv) { RMB rmbA(1, 9, 0); RMB rmbB(2, 5, 0); RMB rmbC = rmbA.Add(rmbB); return 0; }
但是这样看上去好像有点别扭,事实上,在很多不支持运算符重载的语言里,我们都是这样干的。但是在 C++ 里,有一种更好的方式,可以把 + 号进行重载。
我们可以把这个 Add 函数修改成 + 号的重载:
RMB.h
class RMB { public: RMB(int _yuan, int _jiao, int _fen); ~RMB(); // RMB & Add(const RMB & rmb); RMB operator + (const RMB & rmb); private: int yuan = 0; int jiao = 0; int fen = 0; };
RMB.cpp
#include "RMB.h" RMB::RMB(int _yuan, int _jiao, int _fen) { yuan = _yuan; jiao = _jiao; fen = _fen; } RMB::~RMB() { } // RMB & RMB::Add(const RMB & rmb) RMB RMB::operator + (const RMB & rmb) { RMB rmbRes(0, 0, 0); // 分 int f = rmb.fen + fen; int f_ = f / 10; rmbRes.fen = f % 10; // 角 int j = rmb.jiao + jiao + f_; int j_ = j / 10; rmbRes.jiao = j % 10; // 元 int y = rmb.yuan + yuan + j_; int y_ = y / 10; rmbRes.yuan = y % 10; return rmbRes; }
在这样修改之后,使用的时候,我们就可以写出来更优雅的代码了。
int main(int argc,char **argv) { RMB rmbA(1, 9, 0); RMB rmbB(2, 5, 0); RMB rmbC = rmbA + rmbB; return 0; }
可以看到我们直接把两个对象用 + 号加了起来,这比之前使用函数看起来会好得多。
在 C++ 中,有很多符号都可以重载,也有一些不能被重载。
查看全部 -
const修饰成员函数时,成员函数无法修改任何成员变量
const成员函数不能调用非const成员函数
查看全部 -
所以,只要你的编译器兼容 C++11 标准,那么你应该使用 nullptr。
查看全部 -
将父类的析构函数声明为虚函数,作用是用父类的指针删除一个派生类对象时,派生类对象的析构函数会被调用。
此时如果析构函数不加 virtual,那么 delete 父类指针的时候,子类的析构就不会被调用,某些情况下会导致内存泄漏。
查看全部 -
我们之前讲述了什么是多态,还用了一个例子,将一个指针的类型做成强转,然后调用 func 函数,就会发现, func 函数会随着被强转的类型的变换而变换,这种函数的关联过程称为编联。按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编和动态联编。
查看全部 -
我们其实可以把一个员工强行转化成程序员,但是这就有可能出问题,就如同我们把 long long 转成 int 就有可能出现问题。
int main(int argc,char **argv)
{
Coder * coder = new Coder();
Staff * staff = coder; // 隐式转换就可以
Coder * coder = (Coder *)staff; // 必须显式转换
return 0;
}查看全部 -
我们之前已经讲过,可以为成员变量和成员函数设置权限修饰符来设置权限。但是这在继承的时候就会产生一个问题:子类中是否要保持对父类成员的权限,而 C++ 将这个选择权交给了程序员。
在 C++ 中,对父类成员的权限,子类中可以进行重新的定义,这个定义就是通过继承时候写的public 来实现的。
可以看到,我们在上述程序中使用了 public 修饰符,那么父类中的成员函数和成员变量将会保持父类的权限。这种是使用最广泛的继承方式,我们把它叫做公有继承。
查看全部 -
private
用来指定私有成员。一个类的私有成员,不论是成员变量还是成员函数,都只能在该类的内部才能被访问
int main(int argc,char **argv)
{
A a;
a.a = 15; // 会报错,因为成员变量是 private 的
return 0;
}public
用来指定公有成员。一个类的公有成员在任何地方都可以被访问。
int main(int argc,char **argv)
{
A a;
a.a = 15; // 不会报错,因为成员变量是 public 的
return 0;
}protected
用来指定保护成员。一般是允许在子类中访问
查看全部
举报