当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 拷贝构造和赋值操作符,C#和本机 C++ 代码的互用性

VC++
在类VC的界面实现中加入目录树
软件换肤技术在 BCB 中的实现
利用非模窗口生成MDI介面
报表输出轻松搞定
Windows 中不规则窗体的编程实现
解说Win32的窗口子类化
使用测试优先方法开发用户界面
一个简单的登录对话框的实现
一个简单的日记本程序
从资源中加载皮肤
一个在RichEdit中添加表情图象的类
ActiveSkin 4.3 软件换肤在VC中的实现
一种另类“关于(About)”对话框的动态显示方法
对话框打印预览及打印
关于如何换肤、子类化的解决方案
制作 MSN、QQ 的消息提示窗口
如何对 BCGControlBarPro 进行换肤
定制个性化的对话框窗口类
改变窗口中的光标形状
更新MFC中的视图,跟踪.NET Framework中的事件

VC++ 中的 拷贝构造和赋值操作符,C#和本机 C++ 代码的互用性


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 87 ::
收藏到网摘: n/a

C++ At Work 专栏...
拷贝构造和赋值操作符,C#和本机 C++ 代码的互用性

原著:Paul DiLascia
翻译:NorthTibet

下载源代码:CAtWork0509.exe (276KB)
原文出处:Copy Constructors, Assignment Operators, and More

  • 拷贝构造,赋值操作符
  • C#和本机 C++ 代码的互用性

我有一个简单的 C++ 问题。我想让我的拷贝构造函数和赋值操作做同样的事情。你能告诉我最佳实现方法吗?

Shadi Hani
乍一看,这似乎是一个答案简单的简单问题:写一个调用 operator= 的构造函数不就行了:
CFoo::CFoo(const CFoo& obj) { *this = obj;}

或者,写一个公用的拷贝方法,拷贝构造函数和 operator= 都调用这个方法也行。就像这样:

CFoo::CFoo(const CFoo& obj) { CopyObj(obj);}CFoo& CFoo::operator=(const CFoo& rhs) { CopyObj(rhs); return *this;}

  对于大多数类来说,这是行得通的,但还有些特殊情况需要考虑。如果你的类包含有数据成员是另一个类的实例会怎样呢?为了弄清楚这个问题,我写了一个测试程序如 Figure 1 所示。它有一个主类 CMainClass,它包含另一个类 CMember 的实例。两个类都有拷贝构造函数和赋值操作,用 CMainClass 的拷贝构造函数调用 operator=,如下面的代码段所示。代码中使用 printf 语句是为了显示何时调用了哪个方法。为了运行构造函数,cctest 程序首先用缺省构造函数创建 CMainClass 实例,然后用拷贝构造函数创建另一个实例:

CMainClass obj1;CMainClass obj2(obj1);

如果你编译并运行 cctest,当构造 obj2 时,你会看到下面的 printf 信息:

CMember: default ctorCMainClass: copy-ctorCMainClass: operator=CMember: operator=

成员对象 m_obj 被初始化了两次!第一次是缺省构造,第二次是赋值时再次被初始化。嘿,这是怎么回事?
  在 C++ 中,赋值和拷贝是不同的,因为拷贝构造函数是对未初始化的内存进行初始化操作,而赋值是对现有的已经初始化的对象进行操作。如果你的类包含其它的类实例作为数据成员,那么拷贝构造在调用 operator=之前必须首先构造这些数据成员。其结果是致使这些成员就像 cctest 那样被初始化两次,明白了吗?当你用赋值操作而不是初始化例程进行成员初始化时,缺省构造函数也会发生同样的事情。例如:

CFoo::CFoo() { m_obj = DEFAULT;}

与下面代码相对:

CFoo::CFoo() : m_obj(DEFAULT){}

  使用赋值方式,m_obj 被初始化两次,而用初始化例程语法,m_obj 只被初始化一次。所以,要如何避免拷贝构造期间额外的初始化呢?当它与你的代码重用初衷相抵触时, 最好的解决俄u方法就是分开实现拷贝构造和赋值操作,即便它们做同样的事情。从拷贝构造中调用 operator= 肯定能行得通,但不是最有效率的实现。我对初始化的建议是:

CFoo::CFoo(const CFoo& rhs) : m_obj(rhs.m_obj) {}

  现在,主拷贝构造用初始化例程调用成员对象的拷贝构造,并且 m_obj 只被其拷贝构造初始化一次。通常情况下,拷贝构造应该调用其成员的拷贝构造。赋值也是如此。并且,它也同样适用于基类:派生类的拷贝构造和赋值操作应该调用对应的基类方法。当然,有时因为一些具体情况,可能你的做法会有所不同——这里我所描述的是通用规则,只有在你遇到强制性原因时才会破坏这个规则。如果你要在基本对象被初始化之后完成一些公共任务,可以将它们放到一个公共的初始化方法中,并在构造函数和 operator= 中调用。


你能告诉我如何从 C# 中调用 Visual C++ 类,对此我需要什么样的语法?

Sunil Peddi
我有一个用 C#(用户界面)和经典的 C++(业务逻辑)写的应用程序。现在我需要从某个用 C++ 写的 DLL中调用一个函数(或方法),该函数在一个用 Visual C++ .NET 编写的 DLL 中。而这个  Visual C++ .NET DLL 又要调用另一个用 C# 写的 DLL。Visual C++ .NET DLL 相当于一个代理。这样做可行吗?我能用 LoadLibrary 调用 Visual C++ .NET DLL 输出的函数,可以得到返回值,但当我试图向 Visual C++ .NET DLL 中的函数传递参数时,我遇到如下错误:
Run-Time Error Check Failure #0—The value