1. C++ 自定义String
c语言常量不能修改,但是可以通过指针修改
const int num = 100;
int *pnum = #
*pnum = 10000;
但是在C++中 const 是不能修改的指针也不行
自定义String
header
#ifndef TEMPC_MYSTRING_H
#define TEMPC_MYSTRING_H
#include <iostream>
using namespace std;
class MyString {
public:
MyString(int len = 0);
MyString(const char *p);
MyString(const MyString &s);
virtual ~MyString();
friend istream &operator>>(istream&in,MyString &s);
friend ostream &operator<<(ostream&out,MyString &s);
public: // 重载=
MyString &operator=(const char *p);
MyString &operator=(const MyString &s);
char &operator[](int index);
public://重载== !=
bool operator==(const char *p) const;
bool operator==(const MyString &s) const;
bool operator!=(const char *p) const;
bool operator!=(const MyString &s) const;
public: //重载<,>
bool operator<(const char *p);
bool operator<(const MyString &s);
bool operator>(const char *p);
bool operator>(const MyString &s);
public:// 类的指针
char *s_str(){
return m_p;
}
const char *c_str2(){
return m_p;
}
int length(){
return m_len;
}
private:
int m_len;
char *m_p;
};
#endif //TEMPC_MYSTRING_H
cpp
//
// Created by 张传伟 on 2020/8/7.
//
#include "MyString.h"
istream &operator>>(istream &in, MyString &s) {
in >> s.m_p;
return in;
}
ostream &operator<<(ostream&out, MyString &s) {
out << s.m_p;
return out;
}
MyString::MyString(int len) {
if(len == 0){
m_len = 0;
m_p = new char[m_len + 1];
strcpy(m_p,"");
}else{
m_len = len;
m_p = new char[m_len + 1];
memset(m_p,0,m_len);
}
}
MyString::MyString(const char *p) {
if(p==NULL){
m_len = 0;
m_p = new char[m_len + 1];
strcpy(m_p,"");
} else {
m_len = strlen(p);
m_p = new char[m_len + 1];
strcpy(m_p,p);
}
}
MyString::~MyString() {
if(m_p != NULL){
delete[] m_p;
m_p = NULL;
m_len = 0;
}
}
MyString::MyString(const MyString &s) {
m_len = s.m_len;
m_p= new char[m_len +1];
strcpy(m_p,s.m_p);
}
MyString &MyString::operator=(const char *p) {
// 旧的内存释放
if(m_p!=NULL){
delete(m_p);
m_len = 0;
}
// 根据p 分配内存
if(p==NULL){
m_len = 0;
m_p = new char[m_len + 1];
strcpy(m_p,"");
} else{
m_len = strlen(p);
m_p = new char[m_len + 1];
strcpy(m_p,p);
}
return *this;
}
MyString &MyString::operator=(const MyString &s) {
// 旧的内存释放
if(m_p!=NULL){
delete(m_p);
m_len = 0;
}
m_len = s.m_len;
m_p = new char[m_len + 1];
strcpy(m_p,s.m_p);
return *this;
}
char &MyString::operator[](int index) {
return m_p[index];
}
bool MyString::operator==(const char *p) const {
return false;
}
bool MyString::operator==(const MyString &s) const {
if(m_len != s.m_len){
return false;
}
return !strcmp(m_p,s.m_p);
}
bool MyString::operator!=(const char *p) const {
if(p == NULL) {
if(m_len == 0){
return true;
} else {
return false;
}
}else {
if(m_len == strlen(p)){
return !strcmp(m_p,p);
} else {
return false;
}
}
}
bool MyString::operator!=(const MyString &s) const {
return !(*this == s);
}
bool MyString::operator<(const char *p) {
return strcmp(this->m_p,p);
}
bool MyString::operator<(const MyString &s) {
return strcmp(this->m_p,s.m_p);
}
bool MyString::operator>(const char *p) {
return strcmp(p,this->m_p);
}
bool MyString::operator>(const MyString &s) {
return strcmp(s.m_p,m_p);
}
Test
int main() {
MyString s1;
MyString s2("s2");
MyString s2_2 = "";
MyString s3 = s2;
MyString s4 = "4444444";
s4 = s2;
s4 = "s2222";
s4[1] = '4';
printf("%c\n",s4[1]);
cout<< s4 << endl;
return 0;
}
2. C++ 基础 const #define
const 总结
- 1 const 可以有效提高代码的可读性,减少bug
- 2 清楚区分输入还是输出参数
const & #define 相同和不同
-
#define
是预处理阶段简单文本替换 - const 编译器处理,提供类型检查和作用与检查
尝试几种 define
-> 定义在外面的
#define ABC 10
void fun1() {
#define ABC1 30
const int ABC2 = 40;
-> 有卸载的
#undef ABC1
}
void fun1() {
-> 定义在里面的
#define ABC1 30
const int ABC2 = 40;
}
测试代码:
#include <iostream>
#include "../jni.h"
using namespace std;
struct Teacher {
char name[20];
int age;
};
int operatorT1(const Teacher *pT) {// 常量指针表示一种输入参数,能够使用不能够修改
// pT->age = 23;
cout << pT->age << endl;
pT = NULL;
}
int operatorT1(Teacher *const pT) {// 输出
pT->age = 23;// 输出参数
cout << pT->age << endl;
// pT = NULL;
}
/**
* 1 const 可以有效提高代码的可读性,减少bug
* 2. 清楚区分输入还是输出参数
*
* const & #define 相同和不同
* #define 是预处理阶段简单文本替换
* const 编译器处理,提供类型检查和作用与检查
* @return
*/
#define ABC 10
void fun1() {
#define ABC1 30
const int ABC2 = 40;
#undef ABC1
}
void fun2(){
cout << ABC1 << endl;
// cout << ABC2 << endl;
}
int main() {
int a = 1;
int b = 10;
const int *c;//常量指针,修饰指针指向的变量,代表指针指向的内存空间,不能修改
c = &a;
cout << *c << endl;
c = &b;
// *c = 20; 常量指针不允许修改指针所指向的内存控件
cout << c << endl;
cout << &a << endl;
cout << *c << endl;
cout << &c << endl;
cout << "------------------" << endl;
int a1 = 100;
int *const e = &a1;//指针常量,修饰的是指针本身,指向不可以改变
// e = &b;
cout << *e << endl;
*e = 20;
cout << *e << endl;
cout << "------------------" << endl;
const int *const d = &a1;//常量指针常量
return 0;
}
3. C++ 类构造函数 new malloc calloc delete 和 C++ 四驱模型
栈
堆
全局区
方法区
malloc/clloc 分配到堆上
/*
- 构造函数
- 没有返回值
- 函数名称和类名相同 ClassName(){}
- 析构函数
- 没有返回值
- 函数名称和类名相同 ~ClassName(){}
*/
- 函数名称和类名相同 ~ClassName(){}
/*
- 默认拷贝函数只可以完成对象的数据成员的简单复制 传值
- 当对象的数据资源是由指针指向堆时,我们需要考虑深拷贝
*/
// new delete /new[] delete[]
// 对象的动态创建和释放
// 在栈上创建对象 和释放对象 与 在堆上创建对象和释放对象 的区别
// 栈
// 1. 在栈上创建的对象,一经创建,对象的大小是无法改变的
// 2. 在栈上的对象 系统自动创建和销毁
// 堆
// 1. 堆上申请的内存空间 是可以动态调整的
// 2. 堆上的申请的空间,必须自己申请与释放
// malloc/calloc free C语言的 是函数
// new delete C++的语法 new delete 它们是属于运算符 不是函数
#include <iostream>
using namespace std;
class Test {
public:
int getA() const {
return a;
}
int getB() const {
return b;
}
Test() {
a = 10;
b = 0;
p = (char *)malloc(100);
strcpy(p,"abcdefghijk");
cout << "构造函数" << endl;
}
Test(int ma){
a = ma;
b = 0;
cout << "有一个参数构造函数a:" << a << ",b:" << b << endl;
}
Test(int ma,int mb){
a = ma;
b = mb;
cout << "有2个参数构造函数a:" << a << ",b:" << b << endl;
}
// 拷贝构造函数
// Test(const Test& obj){
// a = obj.a;
// b = obj.b;
// cout << "拷贝数构造函数a:" << a << ",b:" << b << endl;
// }
Test(const char *arg){
a = 20;
b = 20;
p = (char *)malloc(100);
strcpy(p,arg);
cout << "浅拷贝构造函数" << endl;
}
// 拷贝构造函数,深浅拷贝
Test(const Test& obj){
a = obj.a;
b = obj.b;
p = (char *)malloc(100);
strcpy(p,obj.p);
cout << "深拷贝数构造函数a:" << a << ",b:" << b << endl;
}
void init(int ma,int mb){
a = ma;
b = mb;
}
~Test() {
if(p != NULL) {
free(p);
}
cout << "析构函数a:" << a << ",b:" << b <<endl;
}
//成员函数
void print(){
cout << "a:" << a << ",b:" << b << endl;
}
private:
int a;
int b;
char *p;
};
void copyTest(Test t){
cout << "对象参数传递a:" << t.getA() << ",b:" << t.getB() << endl;
}
void objtest1(){
Test t1;
t1.print();
}
void objtest2(){
// 自动调用 括号法
Test t1(2,3);
Test t2(2);
// 自动调用 = 法
Test t3 = (4,5);
Test t4 = 9;
// 手动调用
Test t5 = Test(1,5);
t1 = t5;// 这个是赋值操作t5 copy 给 t1;
// 调用拷贝构造函数
Test t6 = t5;
Test t7(t5);
}
void objtest3(){
Test t1;
t1.init(2,3);
Test arr[3];
arr[0].init(1,3);
arr[1].init(1,3);
arr[3].init(1,3);
}
void objtest4() {
Test t1(10,20);
Test t2 = t1;
t2.print();
printf("objtest4\n");
copyTest(t2);
}
Test getTest(){
Test t(100,200);
return t;
}
void objtest5() {
Test t = getTest();// 匿名对象转换成有名的
t.print();
}
void objtest6() {
Test t (123,456);
t = getTest();// 出事话过了t,在这样就相当于赋值
t.print();
}
int main() {
// objtest1();
// objtest2();
// objtest3();
// objtest4();
// objtest5();
// printf("objtest5================\n");
objtest6();
return 0;
}
new delete
c 和 C++分配内存
-> c
int *p = (int *)malloc(sizeof(int));//堆分配内存
*p = 10;
free(p);
p=NULL;
-> C++
int *p1 = new int;// 堆申请内存分配基础类型
*p1 = 20;
delete p1;
-> c 数组init
int *array = (int *)malloc(sizeof(int) * 10);//int array[10] C
array[0] = 20;
free(array);
-> C++ 数组
int *array1 = new int[10];//int array[10] C++
array1[2] = 30;
delete[] array1;//数组的释放方式
------------------
class Test1{
public:
Test1(int i) {
cout << "构造函数" << endl;
}
void print(){
cout << m_a << endl;
}
virtual ~Test1() {
cout << "析构函数" << endl;
}
private:
int m_a;
};
-> C
Test1 *pt1 = (Test1 *)malloc(sizeof(Test1));
pt1->print();
free(pt1);
-> C++ 会调用构造和析构
Test1 *pt2 = new Test1(10);
pt2->print();
delete pt2;
4. C++ 继承
结构体继承,默认 public
class继承,默认private
class 继承关系:
内部集成public,private,protected差不多
外部只有public集成才可以访问public修饰成员
家族成员使用:继承protected
外部使用:集成用public
单个继承访问父类成员
class A {
public:
int a = 1;
int b = 2;
void print() {
cout << "A print" << "a:" << a << "b:" << b << endl;
}
};
class B: public A {
public:
int a = 3;
int b = 4;
void print() {
cout << "B print" << "a:" << a << "b:" << b << endl;
}
};
-> b::A.xxxx
B b;
b.print();
b.A::print();
c++ 多继承
5. c++ 多态&virtual
解决多继承的二义性:
class B_ {
public:
int b;
};
class Base1_ :virtual public B_ {
};
class Base2_ : virtual public B_ {
};
class C : public Base1_, public Base2_ {
};
int main() {
C c;
c.b = 100;// 存在继承的二义性,解决方案是使用virtual 虚继承
c.Base1_::b = 20;
c.Base2_::b = 30;
return 0;
}
抽象类,重载和重写
//重写 重载 重定义
//重写 发生在两个类 虚函数重写 多态
//1 虚函数 多态
//2 非虚函数 重定义
//重载
//必须是发生在同一个类之间
//抽象类,无法实例化
class Shape {
public:
virtual void area() = 0;// 关键字 = 0;纯虚函数
// 重载
virtual void func(){
}
// 重写
void print(){
cout << "shape" <<endl;
}
};
class Circle:public Shape{
private:
int r;
public:
Circle(int r=0):r(r){}
virtual void area(){
cout << "circle area:" << 3.14 * r * r << endl;
}
virtual void func(){
}
void printf(){
cout << "Circle" <<endl;
}
};
class Tri:public Shape{
public:
Tri(int a,int h):a(a),h(h){
}
virtual void area(){
cout << "tri area:" << a * h /2 << endl;
}
private:
int a;
int h;
};
int main() {
Shape * shape = nullptr;
Circle c(10);
Tri tri(3,6);
shape = &c;
shape->area();
shape = &tri;
shape->area();
return 0;
}
C++ 类型转化
// (T)expre C 风格
// T(expre) 函数风格
/*
- static_cast<T>(expre)
- dynamic_cast<T>(expre)
- const_cast<T>(expre)
- reinterpret_cast<T>(expre)
*/
类可以向上转型,不能向下
void func(int *i){};
int main() {
double d = 3.14;
int a = (int)d;
int b = int(d);
int b1 = static_cast<int>(d);//c++
int a1 = 3;
const int b2 = (const int)a1;
const int b3 = static_cast<const int>(a1);
const int ad = 12;
// func(&ad);//error
func(static_cast<int *>(&a));
int ma = 0x76;
printf("a = %d,addr=%p,\n",ma,&ma);
int *ap = &ma;
char * mc = reinterpret_cast<char *>(ap);
printf("c = %c,addr=%p,\n",*mc,&mc);
return 0;
}
6. C++ 异常处理
异常demo 析构函数不要抛出异常
void f1()throw(int){
cout << "f1 start" <<endl;
int a;
throw 2;
cout << "f1 end" << endl;
}
void f2()throw(int){
cout << "f2 start" <<endl;
f1();
cout << "f2 end" << endl;
}
void f3(){
cout << "f3 start" << endl;
try {
f2();
}catch(int i){
cout << "exception :" << i << endl;
}
cout << "f3 end" << endl;
}
int main() {
f3();
return 0;
}
7. 友元函数
#include <iostream>
using namespace std;
class Test{
public:
Test(){}
Test(int a, int b) : a(a), b(b) {
}
friend void add1(Test t);
void add(){
a = a + b;
cout << "a:" << a << endl;
}
private:
int a;
int b;
};
void add1(Test t) {
cout << t.a << t.b<< endl;
}
int main() {
Test test;
add1(test);
return 0;
}
//在类的外部类里面的私有的成员变量
//1. 友元函数是没有this指针的
//2. 你要访问的是类的非静态成员,需要对象做参数
//2. 你要访问的是类的静态成员,则不需要对象做参数
//3. 如果做参数的是全局对象,则不需要对象做参数
//为什么要设计友元函数 友元类
//1. java反射 直接修改类的私有属性
//2. 开了一个后门
#include <iostream>
#include <string.h>
using namespace std;//使用命名空间std标准的命名空间
//static
class Test{
public:
void printC(){//成员函数 是不是可以使用静态变量 或者静态函数
cout <<"c: " <<c<<endl;
getC();
}
void addC(){
c = c + 1;
}
static int getC(){//静态成员函数
//静态成员函数 不能调用普通成员函数 或者普通成员变量
cout << "c: " <<c<<endl;
// cout << "a: " << a<<endl;
return c;
}
private:
int a;
int b;//成员变量是 是每个对象 都有一份
static int c;//静态成员变量 类的多个对象共享
};
//1.
int Test::c = 1;
int main01(){
//TODO: static
cout<<"static"<<endl;
//静态成员变量然后初始化
Test t1;
//静态成员函数调用
//1.
t1.getC();
// Test::c = 10;
// int Test::c = 1;//这里不能这么写
//2
Test::getC();
return 0;
}
class Test1{
public:
friend class Test2;//友元类 Test2是Test1的好朋友,
//在Test2中可以访问Test1类的私有的成员变量,私有函数(private/protected)
Test1(){
}
Test1(int a,int b){
this->a = a;
this->b = b;
}
void add(){
a = a +b;
cout << "a: " << a <<endl;
}
int c;
private:
friend void add1(Test1 t);//友元函数的声明方式,友元函数
friend void print1();
int a;
int b;
static int d;
void print(){
cout <<"a: " << a<<" ,b: " <<b <<" ,c: "<<c<<endl;
}
};
class Test2{
public:
void setA(int a){//
t1.c = a;
t1.a= a;
}
void print(){
cout <<"t1.a: " << t1.a<<endl;
t1.print();
}
private:
Test1 t1;
};
Test1 gTest;
//在类的外部类里面的私有的成员变量
//1. 友元函数是没有this指针的
//2. 你要访问的是类的非静态成员,需要对象做参数
//2. 你要访问的是类的静态成员,则不需要对象做参数
//3. 如果做参数的是全局对象,则不需要对象做参数
//为什么要设计友元函数 友元类
//1. java反射 直接修改类的私有属性
//2. 开了一个后门
void add1(Test1 t){
t.a = t.a +t.b;
cout << "a: " << t.a <<t.c<<endl;
}
void print1(){
// cout <<"gTest.a: " << gTest.a << Test1::d<<endl;
}
//类的友元函数
//1. 定义在类的外部
//2. 有权访问类的所有private/protected的成员
int main02(){
//TODO: 友元函数 友元类
cout<<"友元函数 友元类"<<endl;// << >> 原本的一样:位移 流的输入输出
Test1 t1;
// Test1::d = 10;
Test2 t2;
t2.setA(2);
t2.print();
return 0;
}
8. inline的用法和解释
9. C++ 函数运算符重载
10. C++ 静态函数
11. C++ 模板
模板demo
template <typename T>
void swap1(T& a,T&b){
T temp(a);
a = b;
b = temp;
}
int main() {
int i = 1;
int j = 2 ;
swap1(i,j);
cout << "i:" << i <<"j:" << j<< endl;
float m = 3.0;
float n = 4.0;
swap1(m,n);
cout << "m:" << m <<"n:" << n<< endl;
return 0;
}
网友评论