473,386 Members | 1,796 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Instantiating an abstract class

Hi,

For a project I'm working on I'm kind-of-hacking my way around
deriving a class from an interface or such to create a mock, but
instead creating the mock directly. It is usable as the interface type
(as the virtual functions match up), but there is a snag. No members
are initialized, which means it can't be used as the original type if
it has anything but virtual functions. It would be possible to make it
work, if I could call the constructor for the original type, but
because the functions are pure virtual that's not allowed. Deriving
from it would work, but requires me to fill in all the pure virtual
functions with some kind of random function only to never use them.
The last solution also requires you to un-pure-virtualize all the
classes you want to mock just for testing, which seems like a really
bad idea since it is a *lot* more to type.

Is there some kind of hackish or at least usable way of calling the
constructor regardless of pure virtual functions?

Thanks in advance,
Peter Bindels
Oct 16 '08 #1
4 4355
On Oct 16, 10:25 am, "dasca...@gmail.com" <dasca...@gmail.comwrote:
Hi,

For a project I'm working on I'm kind-of-hacking my way around
deriving a class from an interface or such to create a mock, but
instead creating the mock directly. It is usable as the interface type
(as the virtual functions match up), but there is a snag. No members
are initialized, which means it can't be used as the original type if
it has anything but virtual functions. It would be possible to make it
work, if I could call the constructor for the original type, but
because the functions are pure virtual that's not allowed. Deriving
from it would work, but requires me to fill in all the pure virtual
functions with some kind of random function only to never use them.
The last solution also requires you to un-pure-virtualize all the
classes you want to mock just for testing, which seems like a really
bad idea since it is a *lot* more to type.

Is there some kind of hackish or at least usable way of calling the
constructor regardless of pure virtual functions?

Thanks in advance,
Peter Bindels
Soory but we don't 'hack' here.

If your AbstractInterface is pure abstract, then why not derive from
that to provide an Interface type. Your project can then use that
Interface and you the original AbstractInterface to derive that mock
type. Makes sense to me since the mock doesn't need the virtual
functions. It remains to be seen whether the following fullfills
requirements.

Both AbstractInterface and Interface are pure:

#include <iostream>

class AbstractInterface
{
public:
virtual ~AbstractInterface() = 0;
};

AbstractInterface::~AbstractInterface()
{
std::cout << "~AbstractInterface()" << std::endl;
}

class MockInterface : public AbstractInterface
{
};

class Interface : public AbstractInterface
{
public:
~Interface()
{
std::cout << "~Interface()" << std::endl;
}
virtual void foo() const = 0;
};

class ConcreteInterface : public Interface
{
public:
~ConcreteInterface()
{
std::cout << "~ConcreteInterface()" << std::endl;
}
void foo() const
{
std::cout << "ConcreteInterface::foo()" << std::endl;
}
};

int main()
{
ConcreteInterface concrete;
concrete.foo();
MockInterface mock;
}
Oct 16 '08 #2
On Oct 16, 10:07*pm, Salt_Peter <pj_h...@yahoo.comwrote:
Soory but we don't 'hack' here.
The intent was to hack and then encapsulate, so in projects that use
this you get the benefit without the hacking. I'm trying to get this
as portable as possible regardless of the hacking and up to now it
seems to port very well.
If your AbstractInterface is pure abstract, then why not derive from
that to provide an Interface type. Your project can then use that
Interface and you the original AbstractInterface to derive that mock
type. Makes sense to me since the mock doesn't need the virtual
functions. It remains to be seen whether the following fullfills
requirements.
Sounds good, but the abstract interface's constructor won't be called.

A small adjusted example to show what we've accomplished so far:

class Interface
{
public:
* virtual void foo() const = 0;
};

int main()
{
MockRepository mocks;
* Interface *concrete = mocks.newMock<Interface>();
* mocks.ExpectCall(concrete, Interface::foo);
mocks.ReplayAll();
concrete->foo();
mocks.VerifyAll();
}

Given just the interface above, this works already. The point is that
the Interface object isn't constructed per se, so if it contains any
nontrivial member (std::string, other object of sorts) those will not
be initialized properly and will make the mock behave differently from
the original. That's why the question popped up.

What we're trying to accomplish:

class Interface
{
public:
virtual std::string foo(std::string) const = 0;
std::string name;
};

int main()
{
MockRepository mocks;
Interface *concrete = mocks.newMock<Interface>();
concrete->name = "hello world";
mocks.ExpectCall(concrete, Interface::foo).Returns(concrete->name);
mocks.ReplayAll();
cout << concrete->foo();
mocks.VerifyAll();
}

The concrete->name calls the assignment operator on an unconstructed
string because the Interface constructor (auto-generated which calls
the std::string constructor) was not called. We can't find any way of
making that std::string constructed, other than abusing a subclass.

I understand that this isn't regular C++ but it would make the
language much more testable if it were possible. In particular, the
strict pure virtual semantics prevent this from working.

If the mock of Interface could call its constructor before working
around it, that would work fine. It can't do that, unless you first
create a subclass of it without pure virtual functions (like
ConcreteInterface) which then can be overridden again in the mocking
code. ConcreteInterface serves no other purpose in that construction
other than making the constructor accessible. Since it's such a lot of
code to write (for each test, create a full blank implementation for
each interface you want to mock) compared to what it's use is (make
the constructor - that already exists! - accessible) I would like to
find a workaround.

Thanks in advance,
Peter Bindels
Oct 17 '08 #3
On Fri, 17 Oct 2008 01:23:37 -0700 (PDT), "da******@gmail.com"
<da******@gmail.comwrote:

>class Interface
{
public:
* virtual void foo() const = 0;
};

int main()
{
MockRepository mocks;
* Interface *concrete = mocks.newMock<Interface>();
* mocks.ExpectCall(concrete, Interface::foo);
mocks.ReplayAll();
concrete->foo();
mocks.VerifyAll();
}

Given just the interface above, this works already. The point is that
the Interface object isn't constructed per se, so if it contains any
nontrivial member (std::string, other object of sorts) those will not
be initialized properly and will make the mock behave differently from
the original. That's why the question popped up.
Presumably the newMock method is basically allocating some memory and
casting a pointer?

Is it not possible to define a mock class template? Something like...

template<typename T>
class Mock_Implementation : public T
{
public:
virtual void foo () const;
};

template<typename T>
void MockImplementation<T>::foo () const
{
throw Not_Implemented ();
};

The above probably being private to the MockRepository class, then
newMock simply constructs an instance of that.

This is a minor variation of the factory method design pattern.

http://en.wikipedia.org/wiki/Factory_method_pattern

The only reason I can think why this wouldn't work is if you don't
know anything about the Interface class and therefore don't know which
methods to implement. I guess, given the template parameter to the
newMock method, this may well be the case - but it still seems
strange.

I wouldn't be surprised if some distant future C++ standard provides
sufficient reflection features for a template to identify and
implement all pure virtuals for a given class, but I do mean *distant*
future.

Failing the factory method option, I'm not sure there's even a
constructor to call. I mean, yes, there may be some code waiting to be
called from *another* constructor, but there's no way to access it
that I know of, other than to define a derived non-abstract class.

Any code that's generated for that constructor probably isn't suitable
for direct calling even if you could find a way to call it - it will
be designed to be called from another constructor, and may well be
lacking some kind of stub that would be present for non-abstract
constructor code. Though that's only *slightly* intelligent guessing -
my knowledge of C++ implementation doesn't go that deep.

Oct 17 '08 #4
On Oct 17, 1:34*pm, Stephen Horne <sh006d3...@blueyonder.co.ukwrote:
Presumably the newMock method is basically allocating some memory and
casting a pointer?
Mostly that. It also includes a number of ugly structures that
determine, given a member function pointer, what its signature is,
which virtual function it is, they then instantiate a function using
templates for handling that member and put it in the right place.
It'll be open source when I get this bit working (or when I am sure
that it won't be working).
The only reason I can think why this wouldn't work is if you don't
know anything about the Interface class and therefore don't know which
methods to implement. I guess, given the template parameter to the
newMock method, this may well be the case - but it still seems
strange.
Exactly. It's a generic mocking framework and the concept is that
given just a generic header, plus a call to the least of functions you
need to call / type, you can create a mock. So if in any way possible,
I want to prevent you from having to instantiate every class yourself.
For the cases where you have no (public) member variables it's pretty
easy since you can skip the constructor, when you have no pure
virtuals you can just call the constructor, but when you have both you
have to call it but can't... which you're likely to have in template
method classes and in classes with intelligent member variables (event
list members, property-wrapping members) that are meant to be public.
I wouldn't be surprised if some distant future C++ standard provides
sufficient reflection features for a template to identify and
implement all pure virtuals for a given class, but I do mean *distant*
future.
I very much doubt that from ever becoming true, especially as you
don't really need it all that much in code not like this.
Failing the factory method option, I'm not sure there's even a
constructor to call. I mean, yes, there may be some code waiting to be
called from *another* constructor, but there's no way to access it
that I know of, other than to define a derived non-abstract class.
I'm certain that the constructor for the base class is sufficient to
call to create the abstract class, and that the compiler can easily
generate it if you find some way of generating a call to it.

This far I'll handle this case in documentation that, if you have
member variables and pure virtuals, you have to create a subclass.
Since it's a minor use case it's a nuisance, but it would be so nice
to just wrap that bit of typing into one bit of complex code that
saves me tens or hundreds of classes later on.

Thanks for your insight!

Peter
Oct 18 '08 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Dan Sikorsky | last post by:
If we were to define all abstract methods in an abstract class, thereby making that class non-abstract, and then override the heretofore 'abstract' methods in a derived class, wouldn't that remove...
2
by: active | last post by:
Because of an example I followed I've been instantiating Image objects. Now I notice that the documentation says the Image class is an abstract base class. Things seem to be working! Is the...
3
by: Achim Dahlhoff | last post by:
Hi. I'm trying to find out the diffrence between normal classes and classes derived from built-in types. (Which is causing me trouble trying to instantiate a class using C API calls) >>>...
5
by: Anders Borum | last post by:
Hello! Whilst refactoring an application, I was looking at optimizing a ModelFactory with generics. Unfortunately, the business objects created by the ModelFactory doesn't provide public...
7
by: jason | last post by:
In the microsoft starter kit Time Tracker application, the data access layer code consist of three cs files. DataAccessHelper.cs DataAcess.cs SQLDataAccessLayer.cs DataAcccessHelper appears...
0
by: mailforpr | last post by:
Hi. Let me introduce an iterator to you, the so-called "Abstract Iterator" I developed the other day. I actually have no idea if there's another "Abstract Iterator" out there, as I have never...
0
by: emin.shopper | last post by:
I had a need recently to check if my subclasses properly implemented the desired interface and wished that I could use something like an abstract base class in python. After reading up on metaclass...
6
by: curious2007 | last post by:
So here is how I can summarize my situation. In function.hpp I have the following function: virtual void accept(FunctionVisitor<D,R,I>& v) = 0; And in detfunction.hpp I have the following: ...
19
by: sugard | last post by:
I need to access some data which is in an abstract class. Though you cannot inistialise an abstract class. The task to do is gathering data from a textfile where data is in this format.. P...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.