c++笔记

struct定义类,访问级别默认public
class…访问级别默认private


用类实现计算器:

//------------Operarot.h
#pragma once
#ifndef OPERATOR_H
#define OPERATOR_H

class Operator {
private:
	char sign;
	double num1;
	double num2;

public:
	bool setOperator(char op);
	void setParameter(double m1, double m2);
	bool result(double& r);
	void say();
};

#endif

//---------------Operator.cpp
#include "Operator.h"

bool Operator::setOperator(char op) {
	bool ret = false;

	if (('+' == op) || ('-' == op) || ('*' == op) || ('/' == op)) {
		sign = op;
		ret = true;
	}
	else {
		return ret;
	}

	return ret;
}

void Operator::setParameter(double a, double b) {
	num1 = a;
	num2 = b;
}

bool Operator::result(double& r) {
	bool ret = true;
	switch (sign)
	{
	case '/':
		if ((-0.000000001 < num2) && (0.000000001) > num2) {
			ret = false;
			break;
		}
		r = num1 / num2;

		break;
	case '*':
		r = num1 * num2;
		break;
	case '+':
		r = num1 + num2;
		break;
	case '-':
		r - num1 - num2;
		break;
	default:
		ret = false;
	}

	return ret;
}

// --------------------main.cpp

#include "Operator.h"
#include<stdio.h>

int main() {
	Operator op;
	double sum;
	op.setOperator('+');
	op.setParameter(17.8, 25.5);
	if (op.result(sum)) {
		printf("sum = %f\n", sum);
	}

	op.say();
}


/new创建类对象需要指针接收,一处初始化,多处使用
/new创建类对象使用完需delete销毁
/new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间


手动调用重载构造函数:

#include<stdio.h>

class test {
private:
	int m_value;
public:
	test() {
		m_value = 0;
		printf("test()\n");
	}
	test(int v) {
		m_value = v;
		printf("test(int v,v = %d\n", m_value);
	}
};

int main() {
	test t[3] = { test(),test(3),test(5) };

	return 0;
}

构造函数的调用形式:
1、系统自动调用;
2、赋值调用重载有参数函数:test t = 3;3作为参数重载;
3、test t = test(3);
4、test t(3)


数组的深复制

//--------------------------my_arr.h
#pragma once

#ifndef MY_ARR
#define MY_ARR

class my_arr {
private:
	int len;
	int* pi;
public:
	my_arr(int size);
	my_arr(const my_arr& cp);
	bool setElem(int index, int value);
	bool getElem(int index, int& value);
	void free();
	int getLen();
};



#endif

//----------------------------my_arr,cpp

#include "my_arr.h"

my_arr::my_arr(int size) {

	pi = new int[size];

	for (int i = 0; i < size; i++) {
		pi[i] = 0;
	}
	len = size;
}

my_arr::my_arr(const my_arr& cp) {
	len = cp.len;
	pi = new int[cp.len];

	for (int i = 0; i < cp.len; i++) {
		pi[i] = cp.pi[i];
	}
}

bool my_arr::setElem(int index, int value) {
	bool ret = (index > 0) && (index < len);

	if (ret) {
		pi[index] = value;
	}

	return ret;
}

bool my_arr::getElem(int index, int& value) {
	bool ret = (index >= 0) && (index < len);

	if (ret) {
		value = pi[index];
	}

	return ret;
}

void my_arr::free() {
	delete pi;
}

int my_arr::getLen() {
	return len;
}

//---------------------------main.cpp
#include "my_arr.h"
#include<stdio.h>

int main()
{
	my_arr a1(5);
	int value = 0;
	for (int i = 0; i < a1.getLen(); i++) {
		a1.setElem(i, i);
	}

	for (int i = 0; i < a1.getLen(); i++) {
		if (a1.getElem(i, value)) {
			printf("%d\n", value);
		}
	}

	my_arr a2(a1);

	for (int i = 0; i < a2.getLen(); i++) {
		if (a2.getElem(i, value)) {
			printf("%d\n", value);
		}
	}
}

类里面的const成员必须初始化,但是const在类里是一个只读变量,无法赋值。只能用初始化列表进行初始化:

Test() :i(10) {};

成员的初始化列表的顺序不能决定初始化的顺序,是靠声明顺序决定


对于成员的初始化,也只能用初始化列表进行初始化:

#include<stdio.h>

class Value {
private:
	int m;
public:
	Value(int i) {
		printf("i = %d\n", i);
		m = i;
	}
};

class Test {
private:
	Value m2;
	Value m3;
	Value m1;
public:
	Test():m1(1), m2(2),m3(3){};
};

int main()
{
	Test t;

	
}

类中的const变量的空间分配和对象一致,对象在栈上,它就在栈上,反之,就在堆上,


局部对象的构造顺序就是程序的程序执行流。
堆对象:在程序执行流执行到new关键字时对象被创建。


全局对象的构造函数构造顺序是不一定的,应当避免全局对象间的相互依赖。


栈上的对象在return前会调用析构函数,堆上的对象在用delete删除指向它的指针时会调用析构函数


直接调用构造函数时会生成临时对象,生命周期只有一行代码,在构造完成后立即销毁。

class test {
private:
	int mi;
	void init(int i) {
		mi = i;
	}
public:
	test() {
		init(0);
		printf("test()\n");
	}
	test(int i) {
		init(i);
		printf("test(int i)\n");
	}
	void print() {
		//printf("test()\n");
	}
	~test() {
		printf("~test()\n");
	};
};

int main()
{
	test();

	test(10);
	//输出顺序为 test()
	//			~test()
			//	test(int)
	//			~test()

	
}

有多个对象时,它们的构造顺序和析构顺序是相反的

#include<stdio.h>


class test {
private:
	int mi;
public:
	test(int i) {
		mi = i;
		printf("test() : %d\n", mi);
	}
	~test() {
		printf("~test() : %d\n", mi);
	}
};

int main()
{
	test t1(0);   
	test t2(1);
	test t3(3);

	/*输出
	0
	1
	3
	3
	1
	0*/
	
}

栈对象和全局对象类型于入栈和出栈,后构造的先析构。


const修饰的对象只能调用const成员函数,const成员函数只能调用成员函数,const成员函数不能修改成员变量


静态成员变量是对象之间共享的存储区,所以需要在全局从新定义一遍。


静态成员函数不能直接访问成员变量,静态成员函数可以通过类名调用,也可以通过对象调用。


在这里插入图片描述


二阶构造类头文件:

#ifndef _INTARRAY_H_
#define _INTARRAY_H_

class IntArray
{
private:
    int m_length;
    int* m_pointer;

    IntArray(int len);
    IntArray(const IntArray& obj);
    bool construct();
public:
    static IntArray* NewInstance(int length);
    int length();
    bool get(int index, int& value);
    bool set(int index, int value);
    ~IntArray();
};

#endif


类的友元函数或者友元类可以无限制的访问这个类的元素

#include <stdio.h>
#include<math.h>

class distance {
private:
    double x;
    double y;
public:
    friend double func(distance& d1, distance& t2);
    distance(double x, double y) {
        this->x = x;
        this->y = y;
    };
    double getX() {
        return x;
    };
    double getY() {
        return y;
    };
};

double func(distance& d1, distance& d2) {
    double ret = (d1.y - d2.y) * (d1.y - d2.y) + (d1.x - d2.x) * (d1.x - d2.x);
  //这里直接在外部访问了distance类的私有成员。
    ret = sqrt(ret);

    return ret;
}

int main()
{
    distance d1(15, 28);
    distance d2(35.5, 78.2);

    printf("d1[x] = %f,d1[y] = %f\n", d1.getX(), d1.getY());
    printf("d2[x] = %f,d2[y] = %f\n", d2.getX(), d2.getY());
    
    printf("%f", func(d1, d2));

}

操作符重载:

#include <stdio.h>
#include<math.h>

class complex {
private:
    double real;
    double vir;
public:
    complex() :real(0), vir(0) {};
    complex(double real, double vir) {
        this->real = real;
        this->vir = vir;
    };
    double getReal() {
        return real;
    };
    double getVir() {
        return vir;
    };
    complex operator +(const complex& c) {
        complex temp;

        temp.real = this->real + c.real;

        temp.vir = this->vir + c.vir;

        return temp;
    }

};



int main()
{
    complex c1(5,10);
    complex c2(20, 30);

    printf("c1 : %f+%fi\n", c1.getReal(), c1.getVir());
    printf("c2 : %f+%fi\n", c2.getReal(), c2.getVir());

    complex c3 = c1 + c2;

    printf("c3 : %f+%fi\n", c3.getReal(), c3.getVir());

}

在这里插入图片描述
字符串类:string
字符串流类:用于字符串和数字之间的转换:sstream{istringstream输入流,返回值为bool,ostringstream输出流,返回值为本身}

#include <iostream>
#include<sstream>
using namespace std;



int main()
{
    istringstream s("123.999");
    double num;
    s >> num;
    cout << num <<  endl; // 123.999 type:double
   
}

利用string库函数的字符串右移:

#include <iostream>
#include<sstream>
#include<string>
using namespace std;

string string_rightshift(const string& s, int n) {
    string ret = "";
    int m = n % s.length();

    int pos = s.length() - m;
    ret += s.substr(pos);
    ret += s.substr(0, pos);

    return ret;
}

int main()
{
    string s= "jiangweiabc";
    
    cout << string_rightshift(s,3);
   
}

通过函数对象返回有状态的fib函数对象:

#include<iostream>

using namespace std;

class fib {
private:
	int a0;
	int a1;
public:
	fib() {
		a0 = 0;
		a1 = 1;
	}
	fib(int n) {
		a0 = 0;
		a1 = 1;

		for (int i = 0; i < n-1; i++) {
			int temp = a1;
			a1 += a0;
			a0 = temp;
		}
	}
	int operator ()() {
		int ret = a1;
		a1 = a0 + a1;
		a0 = ret;
		return ret;
	}
	void reset() {
		a0 = 0;
		a1 = 1;
	}
};



int main() {
	fib f1(3);
	
	cout << f1() << endl;
	cout << f1() << endl;
}

在这里插入图片描述
上述图片的p成为一个野指针


智能指针创建:

#include<iostream>
using namespace std;

class Test {
private:
    int value;
public:
    Test(int Value = 0) {
        cout << "Test()" << endl;
        this->value = Value;
    }

    void print() {
        cout << value << endl;
    }

    ~Test() {
        cout << "~Test" << endl;
    }
};

class Pointer {
private:
    Test* p;
public:
    Pointer(Test* p = NULL) {
        cout << "Pointer" << endl;
        this->p = p;
    }
    
    Test* operator ->() {
        return p;
    }

    Test& operator *() {
        return *p;
    }
    ~Pointer() {
        cout << "~pointer" << endl;
        delete p;
    }
};

int main()
{
    Pointer p = new Test(10);

    p->print();

    return 0;
}

bool对象以及重载&& ||:

#include<iostream>
using namespace std;

class Test {
private:
    bool value;
public:
    Test(int n) {
        value = n;
    }
    bool getValue() {
        return value;
    }
    bool operator &&(const Test& t) {
        return this->value && t.value;
    }

    bool operator ||(const Test& t) {
        if (this->value) {
            return true;
        }
        else if (t.value) {
            return true;
        }
        else {
            return false;
        }
        
    }
};

int main()
{
    Test t1(0);
    Test t2(1);

    cout << (t1 || t2) << endl;
}

explicit关键字修饰函数对象,可以让系统不进行四则运算或者赋值类的隐式类型转换。

#include<iostream>
using namespace std;

class test {
private:
    int value;
public:
    test() {
        value = 0;
    }
    explicit test(int n) {    //转换构造函数 
        value = n;
    }
    ~test() {};
    int print() {
        return value;
    }

};

int main()
{
    test t;

    cout << t.print() << endl;

    t = 100;    //出错

    cout << t.print() << endl;

}

转换类型有 static_cast<classname>(value) c++推荐写法
classname(value)
(classname)value

不仅普通类型可以转换为对象,对象也可以转换为普通类型:
operator type(){
return…
}
也可以转换为其他的类类型

class test {
private:
    int value;
public:
    test() {
        value = 0;
    }
    explicit test(int n) {
        value = n;
    }

    operator int() {   //类型转换函数
        return value;
    }
    ~test() {};
    int print() {
        return value;
    }

};

int main()
{
    test t1(100);

    int i = t1;

    cout << i << endl;

}

当同时存在类型转换函数和转换构造函数时:编译会出错:

#include<iostream>
using namespace std;

class value {
public:
    value() {};
    value(const test& t) {   //转换构造函数

    }
};


class test {
private:
    int value;
public:
    test() {
        value = 0;
    }
    explicit test(int n) {
        value = n;
    }

    operator int() {   //类型转换函数
        return value;
    }
    ~test() {};
    int print() {
        return value;
    }

};

int main()
{
    test t1(100);

    value e;

    e = t1;

}

这段代码将报错。因此,习惯于将对象的构造函数加上explicit关键字;不进行隐式的转换构造函数。在工程里面无法抑制隐式的类型转换函数,通常用toType的成员函数来代替,显示的调用


子类拥有父类的所有特性,所以子类可以用来给父类初始化和赋值,

protected修饰的对象成员不可以被外部访问,但可以被子类看到,在子类里可以操作protected成员

对象模型和struct类似:可用struct指针模型访问:

#include <iostream>
#include <string>

using namespace std;



class B{
private:
    int a;
    int b;
    char c;
    double d;
public:
    void print() {
        cout << a << endl << b << endl << c << endl << d << endl;
    }

};


struct A {
    int a;
    int b;
    char c;
    double d;
};

int main()
{

    B b;
    b.print(); 

    A* p = reinterpret_cast<A*>(&b);

    p->a = 10;
    p->b = 20;
    p->c = 'a';
    p->d = 3.14;

    b.print();
}

C语言模拟对象的成员函数和成员变量的访问:

#include<stdio.h>
#include<malloc.h>

struct test {
    int mi;
    int mj;
};

void* create_struct(int a,int b) {
    struct test* ret = (struct test*)malloc(sizeof(struct test));

    if (ret) {
        ret->mi = a;
        ret->mj = b;
    }

    return ret;
}

int getI(void* pthis) {
    struct test* ret = (struct test*)pthis;

    return ret->mi;
}

int getJ(void* pthis) {
    struct test* ret = (struct test*)pthis;

    return ret->mj;
}


int main()
{
    void* t = create_struct(1, 2);

    printf("%d", (getI(t)));  //1  

    t->mi = 10;    //这里由于t的类型为void,与结构体类型指针不匹配,所以导致访问出错

    //C语言用这种类型的访问限制来模拟对象和对象函数的访问,外界访问不到私有变量,能能够通过成员函数访问

    //而成员函数时通过传递指针在类型转换为结构体指针操作这个结构体的,模拟了对象的操作

    printf("%d", (getI(t)));
}

抽相类不能创建对象,但可以创建指针。


多重继承指针会偏移:

#include<iostream>
#define pi 3.1415926


using namespace std;

class Base1 {
private:
	int ma;
public:
	int getA() {
		return ma;
	}
};

class Base2 {
private:
	int mb;
public:
	int getC1() {
		return mb;
	}
};

class Child:public Base1,
			public Base2
{
private:
	int c;
public:
	int getC() {
		return c;
	}
};

int main() {

	Child c;
	Base1* pa = &c;
	Base2* pb = &c;

	cout << "pa = " << pa << endl << "pb = " << pb << endl;    
	cout << "c = " << &c << endl;      //只有pa对齐了c的指针,pb会偏移到从他继承来的元素的位置


	return 0;
}

当菱形继承是,最终的子类会产生多余的最高父级的多余变量,在调用最高级父类的方法时,会产生调用不明确的问题,处理这种方法的办法就是在第二重继承是采用虚继承,但是在第三重继承是需要跨过第二层继承去调用最高级父类的构造函数。同时也会产生多余的虚函数表

dynamic_cast关键字可以让在有多个虚函数表的子类进行赋值初始化操作时,检查具体是哪一个父类的虚函数表。并指向它

#include<iostream>
#define pi 3.1415926


using namespace std;



class Student  {
private:
	
public:
	Student()  {
	
	};
	virtual void printA() {
		cout << "base student" << endl;
	}
};

class Teacher
{
private:
public:
	Teacher() {

	}
	virtual void printB() {
		cout << "base teacher" << endl;
	}
};


class Doctor:public Student,
			 public Teacher
{
private:
public:
	Doctor() {

	}
};
int main() {

	Doctor d;

	Student* ps = &d;
	Teacher* pt = &d;
	Teacher* ptt = (Teacher*)ps;

	cout << ps <<  endl << pt << endl;    //pt会相对于ps偏移4个字节;
	ps->printA();
	cout << endl;
	pt->printB();

	ptt->printB();   //这里,它用teacher指针调用printB,理论应该输出base teacher ,但是输出了base student
					//原因是因为在定义ptt指针是用了ps初始化,并没用产生偏移,系统去ps指针对应的虚函数表里找printB函数,
					//找不到,但是他看到了printA,这两个函数又都是虚函数,所以便调用了它,如果这里想要输出我们想要的结果
					//我们不应该用(Teacher*)这种粗暴的方式进行强制类型转换,可以用dynamic_cast关键字,在用这个关键字
					//转换时,他会去检查ps指向的子类,看到它继承了两个父类,变动态的将指针品偏移到了属于它的父类

	return 0;
}


----
多重继承应该采用一个父类多个接口的方法

----
malloc只能申请空间,不能对对象创建和初始化,free只能释放对象的空间,但是free不能自动调用析构函数,所以也不能销毁由这个对象创建出来的内存

```cpp


构造函数不能成为虚函数,析构函数可以


多重继承应该采用一个父类多个接口的方法


malloc只能申请空间,不能对对象创建和初始化,free只能释放对象的空间,但是free不能自动调用析构函数,所以也不能销毁由这个对象创建出来的内存


关于析构函数用虚函数的用法

#include <iostream>
#include <string>

using namespace std;

class Base {
private:
public:
    Base() {
        cout << "Base" << endl;
    }

    virtual ~Base() {   //这里,需要将析构函数声明为虚函数,因为在main函数中delete的是一个Base指针,如果不使用虚寒数,那么这里只调用了
                        //Base的虚构函数,就不会去看Base指针真正指向的是什么类型。
        cout << "~Base" << endl;
    }
};

class Realize :public Base{
private:
public:
    Realize() {
        cout << "Realize" << endl;
    }

    ~Realize() {
        cout <<"~Realize" << endl;
    }
};

int main()
{
    Base* b = new Realize();

    delete b;    


    return 0;

}

在使用一个父类时,需要习惯的将析构函数声明为虚函数,避免内存泄漏


在构造函数和析构函数中不能发生多态行为,因为在构造函数调用之前,虚函数表指针还为被初始化,析构函数执行时,虚函数表指针已经被销毁,因此,在构造函数和析构函数中调用的函数一定是在本类里的。


dynamic_cast关键字使用必须要求父类含有虚函数;如果它转换失败,会返回0,可用于比较


#include <iostream>
#include <string>

using namespace std;

template <typename T>
void Swap(T& a, T& b) {
    a = a + b;
    b = a - b;
    a = a - b;
}

typedef void (FUNA)(int& a, int& b);
typedef void (FUNB)(double& a, double& b);

int main()
{
    FUNA* Pa = Swap;
    FUNB* Pb = Swap;


    cout << Pa << endl << Pb << endl;   //pa != pb

}

这里,pa和pb都用Swap函数初始化,但是地址不一样,说明编译器在编译时会对模板进行一次编译,在使用到具体模板类型时,又会用模板自动创建一个函数进行编译,再把地址赋值给pa和pb

当函数模板和普通函数发生重载是,编译器优先考虑普通函数

fun<>可以强制编译器使用函数模板,不考虑函数重载


类模板的特化:

#include <iostream>
#include <string>

using namespace std;

template
<typename T1,typename T2>
class Test
{
public:
    T2 add(T1 a, T2 b) {
        cout << "add(T1 a, T1 b)" << endl;;

        return a + b;
    }
};

template
<typename T>
class Test <T,T>      //部分特化
{
public:
    T add(T a, T b) {
        cout << "add(T a, T b)" << endl;

        return a + b;
    }
};

template
<>
class Test <int, int>       //完全特化
{
public:
     int add(int a, int b) {
        cout << "add(int a, int b)" << endl;

        return a + b;
    }
};


int main()
{
    Test<int,float>t1;
    cout << t1.add(3, 3.5) << endl;

    Test<double, double>t2;
    cout << t2.add(3.6,8.2) << endl;

    Test<int, int>t3;
    cout << t3.add(5, 8) << endl;
        
}

}

函数模板也可以特化,但是只支持完全特化


用模板实现递归计算的小例子:速度快,在编译器算完:

#include <iostream>
#include <string>

using namespace std;

template
<int N>
class Sum {
public:
    static const int Value = Sum<N - 1>::Value + N;
};


template
<>
class Sum <1>{
public:
    static const int Value = 1;
};
int main()
{
     
    cout << Sum<100>::Value << endl;   //5050
}

单例类:

#include <iostream>
#include <string>

using namespace std;

class OnlyObject {
private:
    static OnlyObject*  c_instance;
    OnlyObject() {
        ;
    }
    OnlyObject(const OnlyObject& obj);
    OnlyObject& operator =(const OnlyObject& obj);
public:
    static OnlyObject* getInstance();

    void get() {
        cout << "this : "<< this << endl;
    }
    

};
OnlyObject* OnlyObject::c_instance = NULL;

OnlyObject* OnlyObject::getInstance() {
    if (c_instance == NULL) {
        c_instance = new OnlyObject();
    }

    return c_instance;
}
int main()
{
    OnlyObject* p = OnlyObject::getInstance();

    p->get();

    OnlyObject* pp = OnlyObject::getInstance();

    pp->get();    //和p相同

}

单例类模板实现

#include <iostream>
#include <string>

using namespace std;

template
<typename T>
class OnlyObject{
private:
    static T*  c_instance;
    
public:
    static T* getInstance();

    
    

};

template<typename T>
T* OnlyObject<T>::c_instance = NULL;

template<typename T>
T* OnlyObject<T>::getInstance() {
    if (c_instance == NULL) {
        c_instance = new T();
    }

    return c_instance;
}

//  class 1;

class test {
private:
    friend class OnlyObject<test>;
    test() {
    };
    test(const test& t);
    test& operator =(const test& t);
public:
    void get() {
        cout << "this : " << this << endl;
    }
};

 //class 2

class test2 {
private:
    friend class OnlyObject<test2>;
    test2() {
    };
    test2(const test2& t);
    test2& operator =(const test2& t);
public:
    void get() {
        cout << "this : " << this << endl;
    }
};

// main

int main()
{
    test* t1 = OnlyObject<test>::getInstance();

    t1->get();

    test2* t2 = OnlyObject<test2>::getInstance();

    t2->get();

}


判断变量是否为指针:

#include <iostream>
#include <string>
#define ISPTR(temp) (sizeof(isPtr(temp)) == sizeof(char)) //这里为了变参函数能够匹配到对象,但又不执行内部语句
                                                           //有sizeof运算符,这个运算符只看返回值类型判断,多以不
                                                           //会执行内部语句,从而依靠判断返回值便可知道是不是指

using namespace std;

class test {
public:
    test() {

    }
    virtual ~test() {

    }
};

template
<typename T>
char isPtr(T* t) {
    return 'd';
}

int isPtr(...) {           //变参函数对于对象来说有些编译器不支持
    return 0;
}

                                                              
int main()
{
    int i = 1;
    int* p = &i;

    cout << ISPTR(i) << endl;     //0
    cout << ISPTR(p) << endl;     //1

    test t;
    test* pt = &t;

    cout << ISPTR(t) << endl;      //0
    cout << ISPTR(pt) << endl;     //1


}

在对象里,构造函数和析构函数避免抛出异常,如果可能有异常,就用二阶构造。

try_catch的另一种用法:

#include <iostream>
#include <string>


using namespace std;

double divide(double i,double j)throw(double)
{
    double temp = 0.00000000000001;
    if (!((-temp < j) && (temp > j))) {
        return i / j;
    }
    else {
        throw 0.0;
    }
}

void interface(double i,double j) try
{
    cout << divide(i, j) << endl;
}
catch (double i) {
    cout << i << endl;
}

int main()
{
    interface(1, 0);


}

mutable用法:

#include <iostream>
#include <string>


using namespace std;

class test {
private:
    mutable int m_value;    //mutable修饰后可改变const值
    mutable int count;
public:
    test(int n = 0) {
        m_value = n;
        count = 0;
    }

    int getValue()const {
        count++;
        return m_value;
    }

    void setValue(int n)const{
        count++;
        m_value = n;
    }

    int getCount()const {
        return count;
    }
};


int main()
{
    test t;

    const test t1(200);
    cout << t.getValue() << endl;
    cout << t.getCount() << endl;

    cout << t1.getValue() << endl;
    cout << t.getCount() << endl;





}

不用mutable对对象变量调用计数的方法:

#include <iostream>
#include <string>


using namespace std;

class test {
private:
    int m_value;    //mutable修饰后可改变const值
    int* const count;
public:
    test(int n = 0):count(new int(0)){
        m_value = n;
        *count = 0;
    }

    int getValue()const {
        (*count)++;
        return m_value;
    }

    void setValue(int n){
        (*count)++;
        m_value = n;
    }

    int getCount()const {
        return *count;
    }
};


int main()
{
    test t;

    const test t1(200);
    cout << t.getValue() << endl;
    cout << t.getCount() << endl;

    cout << t1.getValue() << endl;
    cout << t.getCount() << endl;
}

重载new 和delete将对象存储在静态存储区:

#include <iostream>
#include <string>

using namespace std;

class Test {
    
    static char class_Arr[];
    static char index[];
    static const char class_Number = 4;
public:
    void* operator new(size_t size) {
        void* ret = NULL;
        for (int i = 0; i < class_Number; i++) {
            if (!index[i]) {
                index[i] = 1;
                ret = class_Arr + i*size;
                cout << "allocate :" << ret << endl;
                break;
            }
        }
        return ret;
    }

    void operator delete(void* p) {
        if (p != NULL) {
            char* mem = reinterpret_cast<char*>(p);
            int pos = (mem - class_Arr) / sizeof(Test);
            int flag = (mem - class_Arr) % sizeof(Test);
            if ((flag == 0) && (class_Number > pos) && (0 <= pos)) {
                index[pos] = 0;
                memset(mem, 0, sizeof(Test));

                cout << "free :" << p << endl;
            }
        }
    }
};

char Test::class_Arr[class_Number * sizeof(Test)] = {0};
char Test::index[class_Number] = { 0 };


int main(int argc, char* argv[])
{
    Test* p = new Test;

    delete p;

    Test* pp[5];
    for (int i = 0; i < 5; i++) {
        pp[i] = new Test;
    }
    for (int i = 0; i < 5; i++) {
        delete pp[i];
    }

}

}

new delete / new[] delete[]的内存分配方式是不一样的。
[]为动态数组,当在对象里重载new[]是,实际分配的空间会比期望的多,
是因为需要多的空间保存数组大小

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值