无法实例化抽象类 [英] cannot instantiate an abstract class

查看:99
本文介绍了无法实例化抽象类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好!
下面的代码在VS6.0上运行良好,但是在VS2005,2008中,它给出了编译错误C2559:无法实例化抽象类"
由于派生类调用基类(抽象类)构造函数.

请让我们给出解决方案.

谢谢
Arjun


  class 基本
{
公共:
     int  a;
    根据()
    {
        cout<< " << endl;
    }
    虚拟 无效 f1()=  0 ;

    〜基础()
    {
        cout<< " << endl;
    }

};

 class 派生: public  Base
{
公共:
    衍生的()
    {
        cout<< " << endl;
    }
    无效 f1()
    {
        cout<< " << endl;
    }

    无效 f2()
    {
        Base :: Base(); // 无法实例化抽象类

    }
    〜派生()
    {
        cout<< " << endl;
    }
}; 



由Aescleal添加了代码标签,以便像我这样的小凡人可以阅读它...

解决方案

错误消息说明了一切,这是任何理智的编译器应该为您编写的代码提供的内容.您正在尝试创建Base的抽象实例.

如果您不知道,您将在编写Base::Base()时尝试创建base实例.这是一个未命名的临时对象,将立即进行构建和销毁,但是仍然存在在其中创建对象的请求.

要使您可以创建实例的基础的唯一方法是从f1中删除纯虚拟(= 0)并为其提供实现.没有别的...

而且,如果它在VC ++ 6.0中工作",那又是另一个理由,那就是将该编译器埋在几英尺深的岩石下,并将其视为具有强烈放射性的东西.

干杯,



PS:参考下面的评论...

在我之后重复一遍-您不是在调用构造函数,而是在尝试创建对象的实例.和C ++一样有点混乱:

 Base :: f1(); 


的意思是根据当前对象是什么,显式调用类Base中的f1()",但是:

 Base :: Base(); 


的意思是为基类的对象保留足够大的内存块,在该内存上调用它的默认构造函数,调用它的析构函数,然后将内存放回位存储桶中."


无论如何,只要记住您不要调用构造函数(即使在使用放置new时也是如此),尽管只有在从原始内存初始化新对象时,编译器才为您服务.


<恐怕我想不起来一个实例,希望在派生类的成员函数中调用基类的构造函数.如果我忽略了这种情况,请原谅我.

这意味着如果要声明Derived的实例,然后再调用instanceDerived-> f2(),则该基本构造函数将被调用两次.我的感觉是您应该具有从基类的构造函数中调用的另一个函数(例如,init).然后,您可以选择从f2()成员函数中调用此init方法.

在这里,这在VS2010中可以正常工作(您的代码与您报告的错误相同):

 //  deleteMe.cpp:定义控制台应用程序的入口点.
//  

#include   "  stdafx.h"
 #include   <   iostream  > 

使用 std :: cout;
使用 std :: endl;

 class 基本
{
公共:
     int  a;
    根据()
    {
        cout<< " << endl;
// 在此处分配内存
//  
//  
someNumber =   int ;

// 初始化将mem分配给某个值
在里面();
    }
    虚拟 无效 f1()=  0 ;
 
    〜基础()
    {
        cout<< " << endl;
删除 someNumber;
    }

无效 init()
{
* someNumber = rand()%128;
}
受保护的:
 int  * someNumber;
};
 
 class 派生: public  Base
{
公共:
    衍生的()
    {
        cout<< " << endl;
    }
    无效 f1()
    {
        cout<< " << endl;
    }
 
    无效 f2()
    {
cout<< " <<恩德尔
//  --- Base :: Base(); //无法实例化抽象类---- 
// 不想在这里调用Base :: Base,因为它将重新分配(即分配第二个或更多时间)

// 但是,我们想将分配的内存重置为默认值
在里面();
    }

 int  getSomeNumber()
{
返回 * someNumber;
}

    〜派生()
    {
        cout<< " << endl;
    }
};



 int  _tmain( int  argc,_TCHAR * argv [])
{
{
派生
 int  tmp;

a.f2();
tmp = a.getSomeNumber();
cout<< " << tmp<<恩德尔

a.f2();
tmp = a.getSomeNumber();
cout<< " << tmp<<恩德尔

a.f2();
tmp = a.getSomeNumber();
cout<< " << tmp<<恩德尔
}
getchar();
返回  0 ;
} 



输出:

 Base :: Base()
派生的:: Derived()
f2()
tmp = 35
f2()
tmp = 62
f2()
tmp = 4
派生的::〜Derived()
Base ::〜Base()


Hi All!
The below code works fine VS6.0, but In VS2005,2008 it is giving compilation Error C2559: "cannot instantiate an abstract class"
Due to Derived class calling base class(abstract class) constructor.

Please lets give the solution.

Thanks
Arjun


class Base
{
public:
    int a;
    Base()
    {
        cout<<"Base::Base()"<<endl;
    }
    virtual void f1()= 0;

    ~Base()
    {
        cout<<"Base::~Base()"<<endl;
    }

};

class Derived : public Base
{
public:
    Derived()
    {
        cout<<"Derived::Derived()"<<endl;
    }
    void f1()
    {
        cout<<"Derived::f1()"<<endl;
    }

    void f2()
    {
        Base::Base();  //Cannot instantiate an abstract class

    }
    ~Derived()
    {
        cout<<"Derived::~Derived()"<<endl;
    }
};



Edit by Aescleal: Added code tags so lesser mortals like me can read it...

解决方案

The error message says it all really, it''s what any sane compiler should give you for the code you''ve written. You''re trying to create an instance of Base which is abstract.

In case you don''t know, you''re trying to create the instance of base when you write Base::Base(). It''s an unnamed temporary that''ll be constructed and destructed immediately but there''s still a request to make an object in there.

The only way you''re going to make base something you can create instances of is to remove the pure virtual ( = 0 ) from f1 and give it an implementation. Nothing else will do...

And if it "worked" in VC++6.0 that''s yet another reason to bury that compiler under several feet of rock and treat it like it''s intensely radioactive.

Cheers,

Ash

PS: With reference to the comment below...

Repeat after me - you are not calling the constructor, you''re trying to create an instance of an object. It''s a bit confusing as in C++:

Base::f1();


means "explicitly call f1() as found in the class Base on whatever the current object is" but:

Base::Base();


means "reserve a lump of memory big enough for an object of class Base, call it''s default constructor on that memory, call it''s destructor then drop the memory back in the bit bucket."


Anyway, just remember you don''t call constructors (even when using placement new, although it comes close) the compiler does for you and ONLY when initialising a new object from raw memory.


I''m afraid I''m not able to think of an instance where one would _want_ to call a base class''s constructor in a derived class''s member function. Forgive me if I overlook a situation that this is required.

That would mean that if one were to declare an instance of Derived, following this with a call to instanceDerived->f2(), that the base constructor would be called twice. My feeling is that you should have another function (say, init) that was called from the Base class''s constructor. You then have the option of invoking this init method from within your f2() member function.

Here, this works just fine in VS2010 (your code had same errors that you reported):

// deleteMe.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>

using std::cout;
using std::endl;

class Base
{
public:
    int a;
    Base()
    {
        cout<<"Base::Base()"<<endl;
		// alloc mem here
		//
		//
		someNumber = new int;

		// init alloced mem to some value
		init();
    }
    virtual void f1()= 0;
 
    ~Base()
    {
        cout<<"Base::~Base()"<<endl;
		delete someNumber;
    }

	void init()
	{
		*someNumber = rand()%128;
	}
protected:
	int *someNumber;
};
 
class Derived : public Base
{
public:
    Derived()
    {
        cout<<"Derived::Derived()"<<endl;
    }
    void f1()
    {
        cout<<"Derived::f1()"<<endl;
    }
 
    void f2()
    {
		cout << "f2()" << endl;
		//---  Base::Base();  //Cannot instantiate an abstract class ----
		// don't want to call Base::Base here, since that will re-alloc (i.e allocate for a 2nd or more time)
		
		// BUT, we would like to reset the allocated mem to the default values
		init();
    }

	int getSomeNumber()
	{
		return *someNumber;
	}

    ~Derived()
    {
        cout<<"Derived::~Derived()"<<endl;
    }
};



int _tmain(int argc, _TCHAR* argv[])
{
	{
		Derived a;
		int tmp;

		a.f2();
		tmp = a.getSomeNumber();
		cout << "tmp = " << tmp << endl;

		a.f2();
		tmp = a.getSomeNumber();
		cout << "tmp = " << tmp << endl;

		a.f2();
		tmp = a.getSomeNumber();
		cout << "tmp = " << tmp << endl;
	}
	getchar();
	return 0;
}



Output:

Base::Base()
Derived::Derived()
f2()
tmp = 35
f2()
tmp = 62
f2()
tmp = 4
Derived::~Derived()
Base::~Base()


这篇关于无法实例化抽象类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆