新建一个 WIN32 控制台应用程序,在附加选项里取消勾选“预编译头”,勾选“空项目” 。
完成后,如果选择“类视图”选项卡,那么会看到下面的窗口:
在这个窗口中,将显示所有类的视图,现在当然一个类都没有,可以按照下面的方法来添加:
在 “类视图” 中右击 "Box" ,在弹出菜单中选择 “添加” ---> “类”,如下图所示:
然后,在显示的 “添加类” 对话框中的类种类列表里选择 “C++ 类”,并单击底下的“添加”按钮:
接着出现 “一般 C++ 类向导” (Generic C++ Class Wizard)对话框:
在上面的对话框中,输入你的类名(如 CBox )。
“文件名” :该文件包含由类的函数成员定义组成的类实现,简单的说就是类的可执行代码。
“.h 文件":类定义存储在头文件中。
组织程序的标准方式是,将类定义存入 .h 的头文件中,将定义函数的代码存入 .cpp 的文件中。通常,各个类定义存入各自的头文件中,各个类的实现存入各自的 .cpp 文件中。
实际上,如果我们的类名为 CBox 时,Visual Studio 2010 会自动帮我们把相应的 .h 文件和 .cpp 文件命名为 Box.h 和 Box.cpp 。
如下图所示:
添加完后,单击”完成“ 按钮,此时会发生两件事:
1. 创建包含 CBox 类定义框架的 Box.h 头文件,其中包含无参数的构造函数和析构函数。
2. 创建 Box.cpp 文件,其中包括 CBox 类定义中构造函数和析构函数的框架实现,当然这两个函数体都是空的。
如下图所示:
当切换回”解决方案资源管理器“时,可以看到这两个自动生成的文件已经在”头文件“和”源文件“的文件夹图标下面了:
下面就以上面 Visual C++ 自动提供的代码为基础开发出 CBox 类。
定义 CBox 类
在 Box.h 中,#pragma once 是为了避免重复嵌入同一定义,详见:http://www.groad.net/bbs/read.php?tid-7944.html
现在通过图形化的手段来添加私有数据成员 m_Length ,m_Width 和 m_Hight 。方法是,在 Class View 中右击 CBox,在弹出菜单中选择 ”添加“ ---> ”添加变量“ :
接下来会弹出一个”添加成员变量向导“,在其中我们可以添加数据成员的名称、类型和访问特性等:
这就成功添加了第一个数据成员,其它的数据成员重复上述过程来添加。完成后,Box.h 的代码就变成:
[C++] 纯文本查看 复制代码 #pragma once
class CBox
{
public:
CBox(void);
~CBox(void);
private:
// Length of a box in inches
double m_Length;
// Width of a box in inches
double m_Width;
// Height of a box in inches
double m_Height;
};
事实上,一般情况都不会通过图形界面来逐个添加变量,而是直接书写,这里只是做一个 Visual C++ 的图形化功能的演示。
添加完变量后,如果查看一下 Box.cpp 文件,那么会看到构造函数定义中也已经自动加上了我们刚才添加的数据成员,及其初始化列表,并且各个变量被初始化为 0 ,如下图所示:
接下来要进行的工作是修改构造函数。
定义构造函数
系统帮我们自动生成的构造函数声明是没有参数的,我们可以根据实际情况对其修改,如改成:
[Plain Text] 纯文本查看 复制代码 explicit CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0);
对构造函数声明完成后,就去具体的实现它,具体实现代码写在 Box.cpp 文件中,将其写成:
[C++] 纯文本查看 复制代码 CBox::CBox(double lv, double wv, double hv)
{
lv = lv <= 0.0 ? 1.0 : lv; // Ensure positive
wv = wv <= 0.0 ? 1.0 : wv; // dimensions for
hv = hv <= 0.0 ? 1.0 : hv; // the object
m_Length = lv > wv ? lv : wv; // Ensure that
m_Width = wv < lv ? wv : lv; // length >= width
m_Height = hv;
}
需要注意的是,成员函数形参的初始化列表只能出现在类定义的成员声明中,而不是在函数的定义中;如果在函数的定义中,则产生编译错误。
再接下来就要添加函数成员,使程序更进一步完整。
添加函数成员
同样可以像上面那样通过图形工具添加函数或手动输入。
这是一个计算长方体体积程序。这里可以定义几个函数分别获得该长方体的长宽高以及计算其体积。这几个函数名分别为:GetHeight() , GetWidth() ,GetLength() 以及 Volume() 。这几个函数我们希望将其定义为内联函数。
有人可能认为,可以在 .cpp 文件中定义各个内联函数,然后在这些函数的前面添加 inline 关键字。但关键是,内联函数终究不是”真正的“函数。因为各个函数体的代码必须直接插入到调用它的位置,所以函数定义必须在编译包调用这些函数的文件时可以使用 。如果不能,那么将产生连接器生成的错误,程序将不能运行。
如果我们希望成员函数是内联函数,那么必须在类的 .h 文件中包括函数的定义。在 .h 文件中,这些函数可以在类定义内部定义,也可以紧跟在类定义之后定义。应该将任何需要的全局内联函数放入 .h 文件中,并用 #include 指令将该文件嵌入任何使用这些函数的 .cpp 文件中。
现在在”类视图“选项卡里右击"CBox" ,在弹出菜单中选择”添加 --> ”添加函数“ ,然后就可以在显示的对话框中输入定义函数的数据,如下图所示:
同样方法,分别添加 GetWidth() ,GetLength() 以及 Volume() 这几个函数。
到这里位置,Box.h 文件中的代码就变成了:
[C++] 纯文本查看 复制代码 #pragma once
class CBox
{
public:
CBox(void);
~CBox(void);
private:
// Length of a box in inches
double m_Length;
// Width of a box in inches
double m_Width;
// Height of a box in inches
double m_Height;
public:
double GetHeight(void)
{
return 0;
}
double GetWidth(void)
{
return 0;
}
double GetLength(void)
{
return 0;
}
double Volume(void)
{
return 0;
}
};
在类定义中已经添加了包含内联函数定义的公有部分。当然这些个函数都需要进行相应的修改,比如将它们改为:
[C++] 纯文本查看 复制代码 double GetHeight(void) const { return m_Height; }
double GetWidth(void) const { return m_Width; }
double GetLength(void) const { return m_Length; }
double Volume(void) const { return m_Length*m_Width*m_Height; }
上面函数中加了 const 关键字表示该函数不会改变对象。
当我们在用图形界面添加函数时,如果函数的返回值在下拉列表中没有想要的类型时,那么就自定义给出。下面再演示用向导添加一个带有自定义类型参数和返回值的成员函数:
如上图所示,给函数添加参数时,没增加一个参数,就要点击”添加“按钮,这个形参就会出现在”参数列表“框中,添加完毕后,点击”完成“即可。用同样的方法,可以添加其它的运算符重载成员函数。
完后,我们可以按照自己喜欢的方式在修改与整理上面由向导生成的代码样式。
最后,点击 ”类视图“ 中 Box 左边的小三角形,再点击展开得来的 CBox,这样在底下的窗口中就看到了 CBox 类的所有成员了:
至此,CBox 类的定义就结束了,经过编排后的全部代码如下:
Box.h
[C++] 纯文本查看 复制代码 #pragma once
class CBox
{
public:
public:
explicit CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0);
~CBox(void);
double GetHeight(void) const { return m_Height; }
double GetWidth(void) const { return m_Width; }
double GetLength(void) const { return m_Length; }
double Volume(void) const { return m_Length*m_Width*m_Height; }
// Overloaded addition operator
CBox operator+(const CBox& aBox) const;
// Multiply a box by an integer
CBox operator*(int n) const;
// Divide one box into another
int operator/(const CBox& aBox) const;
private:
// Length of a box in inches
double m_Length;
// Width of a box in inches
double m_Width;
// Height of a box in inches
double m_Height;
};
Box.cpp
[C++] 纯文本查看 复制代码 #include "Box.h"
CBox::CBox(double lv, double wv, double hv)
{
lv = lv <= 0.0 ? 1.0 : lv; // Ensure positive
wv = wv <= 0.0 ? 1.0 : wv; // dimensions for
hv = hv <= 0.0 ? 1.0 : hv; // the object
m_Length = lv > wv ? lv : wv; // Ensure that
m_Width = wv < lv ? wv : lv; // length >= width
m_Height = hv;
}
CBox::~CBox(void)
{
}
// Overloaded addition operator
CBox CBox::operator+(const CBox& aBox) const
{
// New object has larger length and width of the two,
// and sum of the two heights
return CBox(m_Length > aBox.m_Length ? m_Length : aBox.m_Length,
m_Width > aBox.m_Width ? m_Width : aBox.m_Width,
m_Height + aBox.m_Height);
}
// Multiply a box by an integer
CBox CBox::operator*(int n) const
{
if(n%2)
return CBox(m_Length, m_Width, n*m_Height); // n odd
else
return CBox(m_Length, 2.0*m_Width, (n/2)*m_Height); // n even
}
// Divide one box into another
int CBox::operator/(const CBox& aBox) const
{
// Temporary for number in horizontal plane this way
int tc1 = 0;
// Temporary for number in a plane that way
int tc2 = 0;
tc1 = static_cast<int>((m_Length/aBox.m_Length))*
static_cast<int>((m_Width/aBox.m_Width)); // to fit this way
tc2 = static_cast<int>((m_Length/aBox.m_Width))*
static_cast<int>((m_Width/aBox.m_Length)); // and that way
//Return best fit
return static_cast<int>((m_Height/aBox.m_Height))*(tc1>tc2 ? tc1 : tc2);
} |