[菜鸟学C++]拷贝构造函数和赋值运算符

什么是拷贝构造函数,什么时候要用,什么时候需要禁止
http://blog.csdn.net/arssqz/article/details/6361986

为什么要禁止,怎样禁止拷贝构造函数
http://jrdodds.blogs.com/blog/2004/04/disallowing_cop.html
http://c2.com/cgi/wiki?YouArentGonnaNeedIt

编译器存在哪些陷阱
http://www.cnblogs.com/yfanqiu/archive/2012/05/08/2489905.html

Google和Qt的的宏的区别
http://stackoverflow.com/questions/1454407/macros-to-disallow-class-copy-and-assignment-google-vs-qt

典型的Google宏的写法
http://src.chromium.org/svn/trunk/src/third_party/cld/base/macros.h

// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
//
// For disallowing only assign or copy, write the code directly, but declare
// the intend in a comment, for example:
// void operator=(const TypeName&);  // DISALLOW_ASSIGN
// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
// semantically, one should either use disallow both or neither. Try to
// avoid these in new code.
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
  TypeName(const TypeName&);               \
  void operator=(const TypeName&)

主要记录自己碰到的一个问题,编译器显示:

AbstractClass.h:20:12: cannot declare parameter ‘<anonymous>’ to be of abstract type ‘AbstractClass’

其实对于一个比较有经验的人或者理论知识扎实的人,看到这行信息就应该想象到是出现了类似这样的错误

void im_an_error_method(AbstractClass )
{
     ac.im();
 }

参数没有变量名,参数类型是一个抽象类(无法实例化)

可惜我无法确定,因为这个头文件不是我写的,没有足够的证据去指出别人错误的地方。
所以我只能尝试检查自己的代码,结果发现错误的行数是他头文件的

DISALLOW_COPY_AND_ASSIGN(AbstractClass);

这样一行,很奇怪,按道理应该这么写是不应该出错的,因为大家都是这么写的。
于是我尝试将这行注释掉,或者将这行以代码的形式手动展开编译,即这样

AbstractClass(const AbstractClass&);
void operator=(const AbstractClass&);

发现也可以编译通过
想想到这里应该可以看明白为什么编译器错误提示当中有个’anonymous’错误了吧。

最终原因定位在macro有写错,所以在极端情况下就出编译错误了。

最后借用http://www.artima.com/cppsource/bigtwo.html的一个例子来回顾下

class Example {
  SomeResource* p_;
public:
  Example() : p_(new SomeResource()) {}
  ~Example() {
      delete p_;
   }
};

这例子有错误吗?有几处错误?

[菜鸟学C++]抽象类

菜鸟学C++
http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list
理论不懂就实践,实践不行就理论

AbstractClass.h

#ifndef ABSTRACTCLASS_H_
#define ABSTRACTCLASS_H_

class AbstractClass
{
  public:
    AbstractClass();
    virtual ~AbstractClass();
  
  public:
    virtual void im() = 0;
};
#endif /* ABSTRACTCLASS_H_ */

AbstractClass.cc

#include "AbstractClass.h"

AbstractClass::AbstractClass()
{
}

AbstractClass::~AbstractClass()
{
}

void AbstractClass::im()
{}

Main.cc

#include <iostream>

#include "AbstractClass.h"

using namespace std;

class ConcreteClass : public AbstractClass
{
  public:
    ConcreteClass() {};
    virtual ~ConcreteClass() {};

  public:
    virtual void im()
    {
        cout << "ConcreteClass::im" << endl;
    };
};

void hello(AbstractClass *ac)
{
    ac->im();
}

int main(int argc, char* argv[])
{
    AbstractClass *pAC = new ConcreteClass();
    hello(pAC);
    delete pAC;
    pAC = NULL;
    return 0;
}
~/dev/workspace/labs/ccpp/cc_abstract_class$ g++ Main.cc 
/tmp/ccQrfLyb.o: In function `ConcreteClass::ConcreteClass()':
Main.cc:(.text._ZN13ConcreteClassC2Ev[_ZN13ConcreteClassC5Ev]+0x14): undefined reference to `AbstractClass::AbstractClass()'
/tmp/ccQrfLyb.o: In function `ConcreteClass::~ConcreteClass()':
Main.cc:(.text._ZN13ConcreteClassD2Ev[_ZN13ConcreteClassD5Ev]+0x1f): undefined reference to `AbstractClass::~AbstractClass()'
/tmp/ccQrfLyb.o:(.rodata._ZTI13ConcreteClass[typeinfo for ConcreteClass]+0x10): undefined reference to `typeinfo for AbstractClass'
collect2: ld returned 1 exit status

然后这样编译就可以了

~/dev/workspace/labs/ccpp/cc_abstract_class$ g++ Main.cc AbstractClass.cc