Instantiating an abstract class

D

dascandy

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
 
S

Salt_Peter

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;
}
 
D

dascandy

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
 
S

Stephen Horne

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.
 
D

dascandy

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,060
Latest member
BuyKetozenseACV

Latest Threads

Top