Why a C2259 when the problem is utterly different in nature? - c++

When trying to compile the snippet below, I got the error stated:
error C2259: 'cTest': cannot instantiate abstract class
note: due to the following members:
note: void iTest::log(iTest::eLevel): is abstract
note: see declaration of 'iTest::log'
The abstract member function has been defined with the same signature.
Removing the second enum solves the problem though, it wasn't intended anyway.
But still I don't know why a C2259 is given and I can only find that the member should be defined to fix.
class iTest
{
public:
enum eLevel
{
Info,
};
virtual void foo( eLevel l ) = 0;
};
class cTest : public iTest
{
public:
enum eLevel
{
Info,
};
virtual void foo( eLevel l )
{
}
};
int main()
{
iTest* t = new cTest();
}

The reason why you get this error is because the second definition of iTest::foo and cTest::foo do not have the same signature and thus ctest does not implement iTest::foo.
With full names, your declarations are as follows:
class iTest
{
public:
enum eLevel
{
Info,
};
virtual void foo( iTest::eLevel l ) = 0;
};
class cTest : public iTest
{
public:
enum eLevel
{
Info,
};
virtual void foo( cTest::eLevel l )
{
}
};
As one can see, foo(iTest::eLevel) is not the same as foo(cTest::eLevel), thus cTest is still an abstract class and cannot be instantiated.
You can either remove cTest::eLevel completely, or declare cTest::foo as
class cTest : public iTest
{
public:
enum eLevel
{
Info,
};
virtual void foo( iTest::eLevel l )
{
}
};

Related

VC++: Prevent duplicated member variable name declaration in derived class

I am trying to refactor and rewrite some parts of a legacy library. This library has base classes with same variable names repeatedly declared and used in derived classes (caused by copy/paste programming). For example I have:
class MyBaseClass
{
public:
int m_nVar;
protected:
virtual void MyFunc()
{
m_nVar++;
}
public:
MyBaseClass()
{
m_nVar = 1;
}
};
class MyDerivedClass : public MyBaseClass
{
public:
int m_nVar;
protected:
virtual void MyFunc()
{
m_nVar++;
}
public:
MyDerivedClass ()
{
m_nVar = 2;
}
};
This situation causes me problems because I need to move some functionality I need to a more general base class so that MyBaseClass can be derived from it.
class MyNewBaseClass
{
public:
int m_nVar;
protected:
virtual void MyFunc()
{
m_nVar++;
}
public:
MyNewBaseClass()
{
}
};
class MyBaseClass : public MyNewBaseClass
{
public:
MyBaseClass()
{
m_nVar = 1;
}
};
class MyDerivedClass : public MyBaseClass
{
public:
int m_nVar;//this causes me problems, I need to get notifications on occurrences of such situations
public:
MyDerivedClass ()
{
m_nVar = 2; //this assignments has no effect on MyNewBaseClass::m_nVar
}
};
After I make my modifications MyFunc() in a MyDerivedClass instance does not work as the original code (first run on original causes m_nVar = 3, but in my modified code it becomes m_nVar = 2).
I need some kind of compiler error or warning to notify me of all occurrences of such situations or any other solutions to accomplish what I need.
What do you suggest which works in Visual Studio (VC++)?

abstract classes and templates

I do have some general data type and some derived type(s):
class abstract_data { virtual void foo() {}; };
class derived_data : public abstract_data { void foo() {} };
I want to write some classes that work on that data. What I would like to do is:
class abstract_worker {
public:
virtual void apply(abstract_data&) = 0;
};
class derived_worker : public abstract_worker {
public:
void apply(derived_data&) {} ;
};
This is not working, because the compiler asks me to implement void apply(abstract_data&). I see two alternatives.
1.alternative:
class abstract_worker {
public:
virtual void apply(abstract_data&) = 0;
};
class derived_worker : public abstract_worker {
public:
void apply(abstract_data& data) {
derived_data& internal_data = dynamic_cast<derived_data&>(data);
}
};
2. alternative:
template<class DATA_TYPE>
class abstract_worker {
public:
virtual void apply(DATA_TYPE&) = 0;
};
class derived_worker : public abstract_worker<derived_data> {
public:
void apply(derived_data&) { }
};
I don't like both of them. In the 1st alternative the parameter is declared as abstract_data& even though it really needs to be derived_data&.
In the 2nd alternative it gets lost that the parameter is of type abstract_data&. This is even more problematic if apply(abstract_data&) is not pure virtual, but uses some functionality of abstract_data. You run in the situtation where abstract_data& is implicitely required as DATA_TYPE, but not explicitely declared as such.
However, I do want to keep the type relationships.
Is there another way? If not which one would you prefer?
You might use static assert to prevent DATA_TYPE not inheriting from abstract_data:
#include
class abstract_data { virtual void foo() {}; };
class derived_data : public abstract_data { void foo() {} };
class faulty_data { void foo() {} };
template<class DATA_TYPE>
class abstract_worker {
static_assert(std::is_base_of<abstract_data, DATA_TYPE>::value, "DATA_TYPE does not inherit from abstract_data");
public:
virtual void apply(DATA_TYPE&) = 0;
};
class derived_worker : public abstract_worker<derived_data> {
public:
void apply(derived_data&) {}
};
class faulty_worker : public abstract_worker<faulty_data> {
public:
void apply(faulty_data&) {}
};
Output while compiling:
1>------ Build started: Project: Test_Call, Configuration: Debug Win32 ------
1> Source.cpp
1><PROJ_PATH>\source.cpp(9): error C2338: DATA_TYPE does not inherit from abstract_data
1> <PROJ_PATH>\source.cpp(20): note: see reference to class template instantiation 'abstract_worker<faulty_data>' being compiled
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

is virtual inheritance from pure abstract classes (interfaces) necessary

Why is it that in the code below the compiler complains that PureAbstractBase is an ambiguous base class of MultiplyInheritedClass? I realize I have two copies of the PureAbstractBase in MultiplyInheritedClass and that FirstConreteClass and SecondConreteClass should be derived virtually because they're the middle row of the diamond (and that does indeed fix the problem with the code below). But even though I have two copies of the interface why is it that the code in MultiplyInheritedClass does not just override both and unambiguously pick the interface class defined in MultiplyInheritedClass?
#include <iostream>
using namespace std;
class PureAbstractBase {
public:
virtual void interface() = 0;
};
// I know that changing the following line to:
// class FirstConcreteClass : public virtual PureAbstractBase {
// fixes the problem with this hierarchy
class FirstConcreteClass : public PureAbstractBase {
public:
virtual void interface() { implementation(); }
private:
void implementation() { cout << "This is object FirstConcreteClass\n"; }
};
// I know that changing the following line to:
// class SecondConcreteClass : public virtual PureAbstractBase {
// fixes the problem with this hierarchy
class SecondConcreteClass : public PureAbstractBase {
public:
virtual void interface() { implementation(); }
private:
void implementation() { cout << "This is object SecondConcreteClass\n"; }
};
class MultiplyInheritedClass : public FirstConcreteClass,
public SecondConcreteClass {
public:
virtual void interface() { implementation(); }
private:
void implementation() { cout << "This is object MultiplyInheritedClass\n"; }
};
Further, why do I not have issues with the following hierarchy? Doesn't the ConcreteHandler class have three copies of the AbstractTaggingInterface in this case? So why doesn't it have the same issue as the example above?
#include <iostream>
using namespace std;
class AbstractTaggingInterface {
public:
virtual void taggingInterface() = 0;
};
class FirstAbstractHandler : public AbstractTaggingInterface {
public:
virtual void taggingInterface() { cout << "FirstAbstractHandler\n"; }
virtual void handleFirst() = 0;
};
class SecondAbstractHandler : public AbstractTaggingInterface {
public:
virtual void taggingInterface() { cout << "SecondAbstractHandler\n"; }
virtual void handleSecond() = 0;
};
class ThirdAbstractHandler : public AbstractTaggingInterface {
public:
virtual void taggingInterface() { cout << "ThridAbstractHandler\n"; }
virtual void handleThird() = 0;
};
class ConcreteHandler : public FirstAbstractHandler,
public SecondAbstractHandler,
public ThirdAbstractHandler {
public:
virtual void taggingInterface() = { cout << "ConcreteHandler\n"; }
virtual void handleFirst() {}
virtual void handleSecond() {}
virtual void handleThird() {}
};
I am trying to wrap my head around all of this because I had a conversation with a colleague recently where he claimed that if you were inheriting from pure virtual classes (interfaces) without any data members then virtual inheritance was not necessary. I think understanding why the former code example does not work and the latter does would go a long way to getting this straight in my head (and clear up what exactly he meant by his comment). Thanks in advance.
You need virtual inheritance to overcome the diamond-ambiguity:
class FirstConcreteClass : public virtual PureAbstractBase { ... };
class SecondConcreteClass : public virtual PureAbstractBase { ... };
Long-winded explanation: Suppose you have this:
// *** Example with errrors! *** //
struct A { virtual int foo(); };
struct B1 : public A { virtual int foo(); };
struct B2 : public A { virtual int foo(); };
struct C: public B1, public B2 { /* ... */ }; // ambiguous base class A!
int main() {
A * px = new C; // error, ambiguous base!
px->foo(); // error, ambiguous override!
}
The inheritance of the virtual function foo is ambiguous because it comes in three ways: from B1, from B2 and from A. The inheritance diagram forms a "diamond":
/-> B1 >-\
A-> ->C
\-> B2 >-/
By making the inheritance virtual, struct B1 : public virtual A; etc., you allow any baseclass of C* to call the correct member:
struct A { virtual int foo(); };
struct B1 : public virtual A { virtual int foo(); };
struct B2 : public virtual A { virtual int foo(); };
struct C: public B1, public B2 { virtual int foo(); };
We must also define C::foo() for this to make sense, as otherwise C would not have a well-defined member foo.
Some more details: Suppose we now have a properly virtually-inheriting class C as above. We can access all the various virtual members as desired:
int main() {
A * pa = new C;
pa->foo(); // the most derived one
pa->A::foo(); // the original A's foo
B1 * pb1 = new C;
pb1->foo(); // the most derived one
pb1->A::foo(); // A's foo
pb1->B1::foo(); // B1's foo
C * pc = new C;
pc->foo(); // the most derived one
pc->A::foo(); // A's foo
pc->B1::foo(); // B1's foo
pc->B2::foo(); // B2's foo
pc->C::foo(); // C's foo, same as "pc->foo()"
}
Update: As David says in the comment, the important point here is that the intermediate classes B1 and B2 inherit virtually so that further classes (in this case C) can inherit from them while simultaneously keeping the inheritance from A unambiguous. Sorry for the initial mistake and thanks for the correction!
Your first example fails because the compiler cannot disambiguate between the three implementations of implementation(). You are overriding that method in MultiplyInheritedClass, which actually overrides both FirstConcreteClass::implementation and SecondConcreteClass::implementation (once virtual, always virtual). However, both virtual calls still exist in the interface of MultiplyInheritedClass, which makes the call ambiguous at the call site.
The reason that your example works without virtual inheritance is that there is no conflicting implementation of the common base class. Put another way:
class Base
{
public:
void DoSomething() {
std::cout << "TADA!";
}
}
class One : public Base
{
//...
}
class Two : public Base
{
//...
}
class Mixed : public One, public Two
{
//...
}
int main()
{
Mixed abc;
abc.DoSomething(); //Fails because the compiler doesn't know whether to call
// One::DoSomething or Two::DoSomething, because they both
// have implementations.
//In response to comment:
abc.One::DoSomething(); //Succeeds! You removed the ambiguity.
}
Because your example has all pure virtual functions, there's no multiple implementations which the compiler needs to disambiguate. Therefore, only one implementation exists, and the call is unambiguous.
I tried both of the question codes and they worked fine when instantiating an object of the multi-inherited class. It didn't work only with polymorphism, like this for example:
PureAbstractBase* F;
F = new MultiplyInheritedClass();
And the reason is clear: it doesn't know to which copy of the Abstract base class it should be linked (sorry for bad expressions, I understand the idea but can't express it). And since inherting virtaully makes only one copy exist in the derived class, then it's fine.
Also the code of Billy ONeal is not clear at all, what should we place instead of the comments?
If we place:
public:
void DoSomething()
{ std::cout << "TADA!"; }
it works fine, because of no virtuality.
I work on Visual Studio 2008.
Why not do it like this (suggested in Benjamin Supnik's blog entry):
#include <iostream>
class PureAbstractBase {
public:
virtual void interface() = 0;
};
class FirstConcreteClass : public PureAbstractBase {
public:
virtual void interface() { implementation(); }
private:
void implementation() { std::cout << "Fisrt" << std::endl; }
};
class SecondConcreteClass : public PureAbstractBase {
public:
virtual void interface() { implementation(); }
private:
void implementation() { std::cout << "Second" << std::endl; }
};
class MultiplyInheritedClass : public FirstConcreteClass,
public SecondConcreteClass
{
public:
virtual void interface() { implementation(); }
private:
void implementation() { std::cout << "Multiple" << std::endl; }
};
int main() {
MultiplyInheritedClass mic;
mic.interface();
FirstConcreteClass *fc = &mic; //disambiguate to FirstConcreteClass
PureAbstractBase *pab1 = fc;
pab1->interface();
SecondConcreteClass *sc = &mic; //disambiguate to SecondConcreteClass
PureAbstractBase *pab2 = sc;
pab2->interface();
}
which gives:
Multiple
Multiple
Multiple
This way:
no virtual bases are involved (do you really need them?)
you can call the overriden function via a an instance of the MultiplyInheritedClass
ambiguity is removed by a two-stage conversion

C++ Inheritance problem

I have a class as follows:
Class A
{
virtual int doSomethingCool() = 0;
};
Class B : public A
{
int doSomethingCool();
};
Now the problem likes , I have a set of classes whcih are dependent on A as interface. I need to change the prototype of the function for one of the derived classes. i.e. i need to pass it a parameter.
Class C: public A
{
int doSomethingCool(int param);
};
Any suggestions how i can achieve this ?
No, you don't need to add it to the base class.
class A
{
public:
virtual int doSomethingCool() = 0 {}
};
class B : public A
{
public:
int doSomethingCool() {return 0;}
};
class C: public A
{
private:
int doSomethingCool(); // hide base class version!
public:
int doSomethingCool(int param) {return param;}
};
You can still call doSomethingCool() if done through a base class pointer:
C c;
//c.doSomethingCool (); // doesn't work, can't access private member
c.doSomethingCool (42);
A &a = c;
a.doSomethingCool ();
//a.doSomethingCool (42); // doesn't work, no member of A has that signature
Add it to the interface and default it to call the existing method. You don't have to do the default but don't make it pure otherwise all derived classes will have to implement. It might be better to leave it undefined or to throw. Depends on what you want to achieve.
class A
{
public:
virtual int doSomethingCool() = 0;
virtual int doSomethingCool(int param) {doSomethingCool()};
};
Make the function doSomethingCool() take the int parameter in A.
class A
{
public:
virtual void doSomethingCool(int param) = 0;
};
There's no problem. You can do it. The only caveat is that it will not be treated as an override of the base class virtual function.
class A
{
public:
virtual void doSomethingCool() = 0;
};
class B : public A
{
public:
void doSomethingCool();
};
class C: Public A
{
public:
void doSomethingCool(int param);
};
int main(){}
So while technically possible, you may really want to relook at the design of your interface class A.
One option may be to provide a default argument to A::doSomethingCool
virtual void doSomethingCool(int = 0) = 0;
This isn't syntactically correct C++.
No you can't change a prototype. How would it be used? What would be the value of the param if the non-parametric version would be called?
I would have introduced another, more specific, interface:
struct A
{
virtual int doSomethingCool() = 0;
};
struct A_specific : A
{
virtual int doSomethingCoolWithThis(int i) = 0;
};
class ConcreteA : public A
{
int doSomethingCool() { return 0; }
};
class ConcreteA_specific : public A_specific
{
int doSomethingCool() { return 0; }
int doSomethingCoolWithThis(int param) { return param; }
};
Then I would program to the correct interface:
int main()
{
const A& a1 = ConcreteA();
const A_specific& a2 = ConcreteA_specific();
a1.doSomethingCool();
a2.doSomethingCool();
a2.doSomethingCoolWithThis(2);
}
Just to give you another idea ;-)
Good luck!

Why can't i set a member variable of an interface class as follows

So i have a interface class
class interfaceClass
{
public:
virtual void func1( void ) = 0;
virtual void func2( void ) = 0;
protected:
int m_interfaceVar;
}
and a class that inherits from it.
Why can't i set the member variable of the interface class as follows.
class inhertitedClass : public interfaceClass
{
inheritedClass(int getInt): m_interfaceVar(getInt){};
~inheritedClass(){};
}
and i have to do it like this
class inhertitedClass : public interfaceClass
{
inheritedClass(int getInt){ m_interfaceVar = getInt;}
~inheritedClass(){};
}
I'm sorry if this is a dumb question, but i just ran in to it the other night while i was switching my abstract class into an interface class (the back to an abstract class).
The initializer list in a constructor can specify the ctor for the base classes first and foremost. By depriving interfaceClass of a (protected) constructor (which it obviously should have) you've cut off that lifeline.
So add that protected ctor, e.g.:
class interfaceClass
{
public:
virtual void func1( void ) = 0;
virtual void func2( void ) = 0;
protected:
int m_interfaceVar;
interfaceClass(int x) { m_interfaceVar=x; }
}
and then you can do things the right way, namely
class inhertitedClass : public interfaceClass
{
inheritedClass(int getInt): interfaceClass(getInt){};
~inheritedClass(){};
}
By the time inheritedClass gets to it's initializer list, m_interfaceVar has already been initialized. You can't initialize it a second time.
Your options are to provide a constructor to interfaceClass that initializes m_interfaceVar, or just assign it in the body of inheritedClasss constructor:
interfaceClass(int getInt) : interfaceVar(getInt){}
...
inheritedClass(int getInt) : interfaceClass(getInt)
{
}
or
inheritedClass(int getInt)
{
m_interfaceVar = getInt;
}
Try it like this:
class interfaceClass
{
public:
virtual void func1( void ) = 0;
virtual void func2( void ) = 0;
protected:
// Ctor - called from derived classes
interfaceClass(int interfaceVar)
: m_interfaceVar(interfaceVar){};
int m_interfaceVar;
}
class inhertitedClass : public interfaceClass
{
inheritedClass(int getInt)
: interfaceClass(getInt){}; // Pass to base class ctor
~inheritedClass(){};
}
...in fact, if you don't create a protected or private constructor for interfaceClass, the compiler will silently create one for you, and users will be able to create instances of your interface (you did want it to be an abstract base class, right?)