zoukankan      html  css  js  c++  java
  • 初始化的数值(int、double等)(一)

    首先考虑一个具有几个构造函数的MyClass类。如果我们决定在这个类的私有部分加入一个新的数据成员,称为int_data_:

    class MyClass
    {
    public:
    	MyClass()
    		: int_data_(0)
    	{}
    
    	explicit MyClass(const Apple& apple)
    		: int_data_(0)
    	{}
    
    	MyClass(const string& some_text,double weight)
    		:int_data_(0),some_text_(some_text)
    	{}
    
    private:
    	int int_data_;
    	std::string some_text_;
    };

    加入这个新的数据成员时。须要做大量的工作。

    每次加入一个内置类型的数据成员时。不要忘记在每一个构造函数中对它进行初始化(採用int_data_(0)这种形式)。其实,这是一种easy出错的方法。假设忘了对这个数据成员进行初始化,它非常可能填充了垃圾信息,详细取决于计算机和应用程序曾经的历史。可能导致奇怪且非常难复制的行为。因此,为了防止这种错误。我们应该怎么做?

    首先我们讨论下这个问题是与内置类型有关的。观察std::string类型的数据成员some_text_。

    当我们向MyClass类加入数据成员some_text_时。并不须要在MyClass类的每一个构造函数中对它进行初始化,由于std::string的默认构造函数将会被编译器自己主动调用,把some_text_初始化为一个可反复的状态(此例中为空字符串)。

    可是内置类型并没有构造函数,我们应该怎么办呢?事实上非常easy,对于类的数据成员。不要使用内置类型,而是使用类。例如以下:

    • 不要使用int,改用Int
    • 不要使用unsigned,改用Unsigned
    • 不要使用double。改用Double
    以此类推。我们能够看例如以下代码,即模板类TNumber:

    template <typename T>
    class TNumber
    {
    public:
    	TNumber(const T& x=0)
    		: data_(x)
    	{}
    
    	operator T () const 
    	{
    		return data_;
    	}
    
    	TNumber& operator = (const T& x)
    	{
    		data_ = x;
    		return *this;
    	}
    
    	//后缀操作符x++
    	TNumber operator ++ (int)
    	{
    		TNumber<T> copy(*this);
    		++data_;
    		return copy;
    	}
    
    	//前缀操作符++x
    	TNumber& operator ++ () 
    	{
    		++data_;
    		return *this;
    	}
    
    	TNumber& operator += (T x)
    	{
    		data_ += x;
    		return *this;
    	}
    
    	TNumber& operator 0= (T x)
    	{
    		data_ 0= x;
    		return *this;
    	}
    
    	TNumber& operator *= (T x)
    	{
    		data_ *= x;
    		return *this;
    	}
    
    	TNumber& operator /= (T x)
    	{
    		SCPP_TEST_ASSERT(x!=0,"Attept to divide by 0");
    		data_ /= x;
    		return *this;
    	}
    
    	T operator / (T x)
    	{
    		SCPP_TEST_ASSERT(x!=0,"Attept to divide by 0");		
    		return data_ / x;
    	}
    
    private:
    	T data_;
    };

    首先。接受T类型(T是不论什么内置类型,比如int、double、float等)的构造函数。并没有声明explicit。

    这是有意而为之的。这个类所声明的下一个函数是operator T(),它同意把这个类的实例隐式转换回相应的内置类型。这个类有意设计为非常easy在它与内置类型之间方便地来回转换。它还定义了几个常见的操作符。它们也是使用内置的数值类型时所期望使用的。

    下面是我们能够使用的实际类型的定义:

    <span style="font-size:18px;">typedef TNumber<int> Int;
    typedef TNumber<unsigned> Unsigned;
    typedef TNumber<int64> Int64;
    typedef TNumber<unsigned64> Unsigned64;
    typedef TNumber<float> Float;
    typedef TNumber<double> Double;
    typedef TNumber<char> Char;</span>


    我们应该如何使用像Int和Double这种新类型呢?它们看上去与内置类型相似,仅仅是以大写字母开头。这些类型的使用方法与相应的内置类型全然同样。唯一的差别是它们都有一个默认构造函数把它们初始化为零。

    这样,以MyClass类为例,我们能够採用下面的写法:

    class MyClass
    {
    public:
    	MyClass()
    	{}
    
    	explicit MyClass(const Apple& apple)
    	{}
    
    	MyClass(const string& some_text,double weight)
    		:some_text_(some_text)
    	{}
    
    private:
    	Int int_data_;
    	std::string some_text_;
    };

    在这里。变量int_data_被声明为以大写字母开头的Int类型,而不是int。这样,我们就不须要在全部的构造函数中加入对它进行初始化的代码。它将自己主动被初始化为零。

    实际上另一个差别:当我们使用内置类型时,试图将它除零可能导致不同的结果,详细取决于编译器和操作系统。为了保持一致。这个执行时错误将导致调用与处理其它错误同样的错误处理函数,使我们能够对错误进行调试。

    健壮的代码不应该在变量被初始化之前引用它们。可是,假设确实发生了这种情况。让未初始化的变量具有一个像零这种安全值,显然要比具有随机的垃圾值好得多。

  • 相关阅读:
    eclipse—Maven项目打包成exe
    netty+proto使用简要记录
    使用Kotlin开发第一个Android应用
    Android——调用高德地图API前期准备
    AndroidStudio更改包名
    Android Studio —— java.lang.VerifyError: Verifier rejected class 问题解决
    Android studio Error occurred during initialization of VM 问题解决
    AndroidStudio下使用 RecyclerView xml文件不显示预览条目并报错类似:NoClassDefFoundError 问题解决
    Genymotion模拟器安装问题及解决(启动失败,模拟器不能联网)
    华为荣耀畅玩5C NEM-UL10 ROOT那些事儿(亲测成功)
  • 原文地址:https://www.cnblogs.com/lytwajue/p/7019284.html
Copyright © 2011-2022 走看看