[OOP]函数模板

#include <stdio.h>
#include <string.h>

// 定义一个函数模板
template <typename T>
T findmax (T arr[],  int len)
{
    T  val = arr[0];
    for(int i=1; i<len ; i++)
    {
        if(arr[i] > val) val = arr[i];
    }
    return  val;        
}

template <typename _A, typename _B>
void Test(_A obja, _B objb)
{
}

int main()
{
    int  arr[ 4] = { 1, 42,  87, 100 };
    int  result = findmax <int> (arr,  4);

    double abc[3] = {1.0, 2.0, 3.0};
    double r = findmax<double>(abc, 3);

    // Test<int, double> (10, 12.0);
    return 0;
}

 

[OOP]内部类

#include <stdio.h>
#include <string.h>



class AAA
{
private:
    // 定义一个内部类
    class Inner
    {
    public:
        int id;
        char  name[64];

    };

public:
    AAA()
    {
        Inner i;
        i.id = 123;
    }
};

int main()
{
    // 使用该内部类时,类名使用全称 AAA::Inner
// 	AAA::Inner  a;  
// 	a.id = 123;
// 	strcpy(a.name, "AnXin"); 
// 	printf("Name: %s \n", a.name);
    return 0;
}

 

[OOP]重载输入输出操作符

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class Point
{
public:
    int x, y;
};

// 日志类
class Logger
{
public:
    Logger()
    {
    }

    Logger& operator << (int value)
    {
        printf("%d", value);
        return *this;
    }
    Logger& operator << (double value)
    {
        printf("%f", value);
        return *this;
    }
    Logger& operator << (const char* value)
    {
        printf("%s", value);
        return *this;
    }
    Logger& operator << (const Point& point)
    {
        printf("(%d,%d)", point.x, point.y);
        return *this;
    }

    Logger& Print(const char* value)
    {
        printf("%s", value);
        return *this;
    }
    Logger& Print(const Point& point)
    {
        printf("(%d,%d)", point.x, point.y);
        return *this;
    }
};

int main()
{
    Logger lg;


    Point pt;
    pt.x = 12;
    pt.y = 13;
    //lg << 1 << "," << 11.01 << "hello" << pt << "\n";


    lg.Print("hello").Print("world");
    return 0;
}

 

[OOP]重载类型转换操作符

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class Fraction
{
public:
    Fraction(): num(1), den(1)
    {
    }
    Fraction(int n, int d) : num(n), den(d)
    {
    }

    // 类型转换操作符
    operator double()
    {
        return (double)num/den;
    }

public:
    int num;
    int den;
};


int main()
{
    Fraction fa(4,5);
    double value = (double) fa;
    printf("%f \n", value);

    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class Text
{
public:
    Text(const char* str)
    {
        // 申请一块内存, 保存此字符串
        m_size = strlen(str) + 1;
        m_buf = new char[m_size];
        strcpy(m_buf, str);		
    }
    ~Text()
    {
        // 释放此字符串
        delete [] m_buf;
    }

    // 类型转换操作符
    operator const char* ()
    {
        return m_buf;
    }

private:
    int m_size;
    char* m_buf;
};

int main()
{
    Text t1("hello world");
    
    const char* txt = (const char*) t1;
    printf("text: %s \n", txt);
    return 0;
}

 

[OOP]重载关系操作符

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class Fraction
{
public:
    Fraction(): num(1), den(1)
    {
    }
    Fraction(int n, int d) : num(n), den(d)
    {
    }

    bool operator == (const Fraction& other)
    {
        if(num * other.den  == den * other.num)
        {
            return true;
        }
        return false;
    }

public:
    int num;
    int den;
};


int main()
{
    Fraction fa(2, 3);
    Fraction fb(4, 6); // 4/6 2/3
    if(fa == fb)
    {
        printf("equal\n");
    }
    else
    {
        printf("not equal\n");
    }

    return 0;
}

 

[OOP]重载元素操作符

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class Text
{
public:
    Text(const char* str)
    {
        // 申请一块内存, 保存此字符串
        m_size = strlen(str) + 1;
        m_buf = new char[m_size];
        strcpy(m_buf, str);		
    }
    ~Text()
    {
        // 释放此字符串
        delete [] m_buf;
    }

    char& operator[] (int index)
    {
        return m_buf[index];
    }

private:
    int m_size;
    char* m_buf;
};

int main()
{
    Text t1("helloworld");
    char ch = t1[0];
    t1[0] = 'H';
    return 0;
}

 

[OOP]重载算术操作符

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class Fraction
{
public:
    Fraction(): num(1), den(1)
    {
    }
    Fraction(int n, int d) : num(n), den(d)
    {
    }

    // 重载加号操作符
    Fraction operator + (const Fraction& other)
    {
        Fraction result;
        result.den = den * other.den; // 分母相乘
        result.num = num*other.den + den * other.num; // 分子交叉相乘
        return result;
    }

public:
    int num;
    int den;
};

// 重载全局操作符
Fraction operator + (const Fraction& a, const Fraction& b)
{
    Fraction result;
    result.den = a.den * b.den; // 分母相乘
    result.num = a.num * b.den + a.den * b.num; // 分子交叉相乘
    return result;
}

int main()
{
    Fraction fa(2, 3);
    Fraction fb(3, 5);
    Fraction fc = fa + fb;

    return 0;
}

 

[OOP]友元函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class Object
{
    friend void Print(Object* p);

public:
    Object(int v) : value(v)
    {
    }
private:
    int value;
};

void Print(Object* p)
{
    printf("value: %d \n", p->value);
}


int main()
{
    Object obj(10);
    Print(&obj);
    return 0;
}

 

[OOP]深度拷贝

//当以下情况发生时,需要添加拷贝构造函数。示例:

class Text
{
public:
    Text(const char* str)
    {
        // 申请一块内存, 保存此字符串
        m_size = strlen(str) + 1;
        m_buf = new char[m_size];
        strcpy(m_buf, str);		
    }
    ~Text()
    {
        // 释放此字符串
        delete [] m_buf;
    }
private:
    int m_size;
    char* m_buf;
};


int main()
{
      // 定义第一个对象
    Text t1("helloworld");

      // 第二个对象以t1为蓝本进行拷贝
    Text t2(t1);

    return 0;
}

出什么会出错?

// 对象创建
对象t1.m_buf,指向一块内存
对象t2拷贝了t1, t2.m_buf指向了同一块内存

// 对象析构
对象t1析构, delete [] m_buf;
对象t2析构,delete [] m_buf;出错,此块内存已经被delete

错误的根本原因:应该拷贝其数据,而不是拷贝其指针。

 

(1) 正规解决方法
添加拷贝构造函数,拷贝其具体的数据

Text(const Text& other)
{
m_size = other.m_size;
m_buf = new char[m_size];
strcpy(m_buf, other.m_buf);
}
此种情况称为“深度拷贝”

(2) 省事的办法
禁止用户进行拷贝构造,将拷贝构造函数设定为private。

private:
Text(const Text& other)
{
}

[OOP]拷贝构造函数

拷贝构造函数是一种特殊的构造函数。copy constructor
它是构造函数,所以函数名是类名、没有返回值
它是特殊的构造函数:参数形式是固定的

class Object
{
public:
Object( const Object& other );
};

拷贝构造函数的含义: 以一个对象为蓝本,来构造另一个对象。

Object b;
Object a(b); // 或写成 Object a = b;

称作:以b为蓝本,创建一个新的对象a。

(a是b的一个拷贝/备份,两者内容完全相同)

 

拷贝构造函数从来不显式调用,而是由编译器隐式地调用。
在以下三种情况:
(1)定义对象
Object a;
Object b(a); // 或写成 Object b = a;

(2)动态创建对象
Object a;
Object* p = new Object(a);

(3)函数的传值调用
void Test(Object obj);

构造:
Object a;
Object b = a; // 或写作 Object b(a);
// 此为“构造”,在创建对象的时候给初值,拷贝构造函数被调用

赋值:
Object a(1,2);
Object b;
b = a; // 此为“赋值”,不会调用拷贝构造函数

在拷贝构造函数,可以访问参数对象的任意成员

因为它们是同类,所以访问不受限制。

Object(const Object& other)
{
this->a = other.a;
this->b = other.b;
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


class Object
{
public:
    Object(int a, int b)
    {
        this->a = a;
        this->b = b;
    }
    Object(const Object& other)
    {
        printf("in copy constructor...\n");
        this->a = other.a;
        this->b = other.b;
    }
private:
    int a;
    int b;
};

void Test(Object obj) // Object obj(x)
{

}

int main()
{
    Object x(1,2);

    Test(x);

// 	Object y(x); // copy
// 	Object* p = new Object(x);
// 
// 	delete p;
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class Base
{
public:
    int dddd;
};
class Object : public Base
{
public:
    Object(int a, int b)
    {
        this->a = a;
        this->b = b;
    }
    Object(const Object& other):Base(other)
    {
        this->a = other.a;
        this->b = other.b;
    }
private:
    int a;
    int b;
};

int main()
{
    Object objx(1,2);
    objx.dddd = 123;

    Object objy(objx);

    return 0;
}