C++ day5 模板、面试题、重载string类

一、day4作业 -- 运算符重载封装string函数 -- 记得再写一遍

用重载运算符封装string类:=表示赋值,+表示产生一个新的字符串(用strcat来实现,不等同于实现strcat),==表示判断是否相等。//这里是我没理解题意,尤其是+重载

c=a+b;  a=b;   c明显是个新的对象,所以返回值用Mystring  

为了便于理解,我又写了个重载+=

#include<iostream>
#include <assert.h>
#include <string.h>

using namespace std;

class String{
	public:
		String(const char *str) 
		{
			int len = strlen(str)+1;
			ptr = new char [len];
			assert(NULL != ptr);
			strcpy(ptr,str);
		}

		~String()
		{
			delete [] ptr;
		}

	public:
		String operator +(const String &obj)
		{
			int len = strlen(this->ptr) + strlen(obj.ptr) + 1;//计算长度
			char *p = new char [len];
			assert(NULL != p);

			strcpy(p,this->ptr);
			strcat(p,obj.ptr);

			String tmp(p);//构造对象
			delete [] p;

			return tmp;
		}

		String & operator =(const String &obj)
		{
			int len = strlen(obj.ptr)+1;
			delete [] ptr;
			ptr = new char[len];
			assert(NULL != ptr);

			strcpy(this->ptr, obj.ptr);

			return *this;
		}
        String & operator +=(const String &obj)     //重载+=
        {
            int len = strlen(obj.ptr)+strlen(this->ptr)+1;  
            char *p = new char[len];
            strcpy(p,this->ptr);
            strcat(p,obj.ptr);

            delete [] ptr;          
            ptr = new char[len];
            assert(NULL != ptr);
            strcpy(this->ptr, p); 
            delete [] p;

            return *this;
        }


		int operator == (const String &obj)
		{
			return ((strcmp(this->ptr,obj.ptr) == 0) ? 1 : 0);
		}
		int operator != (const String &obj)
		{
			return ((strcmp(this->ptr,obj.ptr) == 0) ? 0 : 1);
		}

		friend ostream & operator << (ostream &, const String &);

	private:
		char *ptr;
};
		
ostream & operator << (ostream &os, const String &obj)
{
	os << obj.ptr;
	
	return os;
}

int main()
{
	String a = "hello";
	String b = "world";
	String c = a+b;
	cout << c << endl;

	a = b;
	cout << a << endl;
	cout << b << endl;

	a = c;

	cout << (a == b) << endl;

	return 0;
}

二、C++面试题

C和C++的结构体区别-能否定义函数
C不能有函数,但可以有函数指针
C++可以有函数,默认权限public
C++的结构体和类的区别--默认权限(继承、成员)
C++结构体默认public
C++类默认private
C和C++的区别
面向过程/对象C主要面向过程,C++主要面向对象(侧重于类的设计而非逻辑)
适用方向不同C要求效率高代码体积小(如Linux系统就是C编写的),C++适用于更上层
C++是C的扩充
引用和指针的区别
操作方式指针是存变量地址(间接),引用是取别名(直接)
内存指针占内存,引用不占内存
指向指针可以为空且可更改,引用必须初始化且不可更改
指针有多级指针
static在C中的使用
修饰局部变量延长生命周期,程序结束释放(ps:循环中还能防止重复定义)
修饰全局变量限制本文件使用(全局变量定义在源.c文件中)
修饰函数限制本文件使用
C++中值的三种传递方式
值传递int 
地址传递int *
引用传递int &
C和C++中,频繁使用的短小函数怎么实现
C宏定义(编译阶段)
C++inline
assert

宏,用于检查不应该发生的情况,比如assert(ptr!=NULL);好用

C中也能用

const相比#define的优点
const更安全const有数据类型,编译器可以进行安全检查,后者只是单纯的字符替换
const可以调试宏定义不能
new/delete 与 malloc/free
本质不同malloc是C/C++库函数,new是C++运算符
C++对象需要

方便编译阶段执行构造函数和析构函数时,创建/释放空间。(而库函数不在编译器的控制权限之内)

new:动态内存分配和初始化

delete:清理和释放内存

内存溢出和泄露
溢出内存不够导致申请内存失败
泄露无法成功释放内存,导致内存堆积
malloc(0)返回一个空指针。检查返回值是否为NULL来判断是否能够正常动态分配内存
解决内存溢出

异常处理函数

if(ptr==NULL)  return -1;或者

assert(ptr!=NULL);

三、函数模板

模板是泛型编程的基础

泛型编程:编写与类无关的代码        //主函数使用举例:add<int>(m,n);

总结:

头部声明:template <class T >

外部定义:template <class T>

作用域访问符:Demo::

主函数:Demo obj;

      #include<iostream>
      using namespace std;
      //函数模板声明
      template <class T> //T:int\double\char\Demo...  这里class和类无关
      T add(T &a, T &b);

      class Demo{
         public:
            Demo(int val) : val(val)
            {
               cout << __func__ << ":" << __LINE__ << endl;
            }
         public:
            void setval(int val)
            {
               this->val = val;
            }

            int getval() const
            {
               return this->val;
            }
         private:
            int val;
};
template <class T>
T add(T &a,T &b)
{
    T c = a+b;
    return c;
}

      int main()
      {
         int m = 10;
         int n = 20;

         double d = 1.2;
         double e = 2.3;

         Demo a(333);
         Demo b(333);

         int ret = add<int>(m,n);//T:int
         cout << ret << endl;

         double f = add<double>(d,e);//T:double
         cout << f << endl;

         Demo c = add<Demo>(a,b);//T:Demo
         cout << c << endl;

         return 0;
      }

四、类模板       

//主函数使用举例:Demo<int> obj(100);创建对象,而非原来的Demo obj(100)

类模板的构造函数不能给定默认值(T都不确定)

总结:

比上个函数模板,区别在于头部声明紧跟类

头部声明:template <class T>

外部定义:template <class T>

作用域访问符:Demo<T>::

主函数:Demo<int> obj;

#include<iostream>
using namespace std;
template <class T>
class Demo{
    public:
        Demo(T val):val(val){
            cout << __func__ << ":" << __LINE__ << endl;
        }
        void setval(T val);
        T getval() const;
    private:
        int val;
};
template<class T>
void Demo<T>::setval(T val)
{
    this->val = val;
}
template<class T>    //外部定义必须加模板声明
int Demo<T>::geival()
{
    return this->val;
}

int main()
{
    Demo<int> obj(100);
    obj.setval(200);
    cout<<obj.getval()<<endl;

    return 0;
}

五、非类型模板参数

template <class T,int len>               

class Demo{

};

//注意index还是用int,不用T

总结:

比上个类模板,头部声明多了确定的参数类型,需要主函数创建对象时初始化

头部声明:template <class T,int len>

外部定义:template <class T,int len>

作用域访问符:Array<T,len>::

主函数:Array<int,10> obj;

#include<iostream>
#include<assert.h>
using namespace std;
template <class T,int len>    //len表示数组长度
class Array{
    public:
        Array(){
            ptr = new T[len];
            assert(ptr!=NULL);
        }
        ~Array(){
            delete [] ptr;
        }
    public:
        void setval(int index,T val);    //index就可以不用T?
        T getval(int index) const;
    private:
        T *ptr;
};
template <class T,int len>
T Array<T,len>::getval(int index) const
{    
    return ptr[index];
}

int main()
{
    Array<int,10> a;    //记得主函数用一个整数表示len 
    int i;
    for(i=0;i<10;i++)    //注意这里和数组长度对应
    {
        a.setval(i,i+1);    //还是不习惯对象访问
    }
    for(i=0;i<10;i++)
    {    
        cout<<a.getval(i)<<" ";
    }
    cout<<endl;
        return 0;
}

六、默认类型模板参数

给类模板的形参指定默认值                

template <class T=int, int len=10>

总结:

比上个非类型模板参数,区别在于头部声明(加具体值)和主函数使用(可覆盖)

头部声明:template <class T=int, int len=10>

外部定义:template <class T,int len>

作用域访问符:Array<T,len>::

主函数:Array<double,20> obj;

      #include<iostream>
      #include<assert.h>
      using namespace std;

      template <class T=int, int len=10>
      class Array{
         public:
            Array(){
                ptr = new T[len];
                assert(ptr!=NULL);
            }
            ~Array()
            {
               delete [] ptr;
            }
        public:
            void setval(T val,int pos);
            T getval(int pos) const;
        private:
            T val;
    };
template <class , int len>    
//类外部成员函数定义的时候就不加具体默认值,template<class int ,int len>
void Array<T,len>::setval(T val,int pos)    //Array<T,len>
{
    ptr[index] = val;
}
template <class T, int len>
T Array<T,len>::getval(int pos) const
{
    return ptr[index];
}

int main()
{
    Array<int,20> obj;
    Array<> obj2;        //也可以就用默认参数,不传参

    return 0;
}


七、友元模板函数--函数模板作为类模板的友元

#include<iostream>
using namespace std;
template<class T>
class Demo
{
	public:
		Demo(T val) : val(val)
		{
			cout << __func__ << ":" << __LINE__ << endl;
		}
		
		Demo(const Demo<T> &obj) //拷贝构造函数
		{
			cout << __func__ << ":" << __LINE__ << endl;

			this->val = obj.val;
		}

		~Demo()
		{
			cout << __func__ << ":" << __LINE__ << endl;
		}

		void setval(T val)
		{
			this->val = val;
		}

		T getval() const;

		template<class M>
		friend ostream &operator <<(ostream &,const Demo<M> &);//友元模板函数

	private:
		T val;
};

//类外部定义成员方法
template<class T>
T Demo<T>::getval() const
{
	return this->val;
}

template<class T>
ostream &operator <<(ostream &os,const Demo<T> & obj)
{
	os << obj.val;
	return os;
}


int main()
{
	Demo<int> obj(666);
	Demo<int> obj1 = obj;

	cout << obj << endl;
	cout << obj1 << endl;

	Demo<double> obj2(1.2);
	cout << obj2 << endl;


	return 0;
}

头部声明:template <class T>

内部friend函数声明:template <class M> friend

外部定义:template <class T>

外部friend函数定义:template <class M/T>

作用域访问符:Demo<T>::

主函数:Demo<int> obj;

  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值