class ZooAnimal {
public:
virtual void draw();
int resolveType() {return myType;}
protected:
int myType;
};
class Bear : public ZooAnimal {
public:
Bear (const char *name) : myName(name), myType(1){}
void draw(){ };
private:
std::string myName;
};
void main()
{
}
When I am compiling above code I am geeting following error
error C2614: 'Bear' : illegal member initialization: 'myType' is not a base or member
Why am I getting the above error, as we can access protected member from the derived class?
You can't initialize base class member in derived class initializer lists.
You'll need to provide a constructor to the base class:
class ZooAnimal {
public:
ZooAnimal(int type) : myType(type) {}
virtual void draw();
int resolveType() {return myType;}
protected:
int myType;
};
and call it from the derived class:
class Bear : public ZooAnimal {
public:
//here//
Bear (const char *name) : ZooAnimal(1), myName(name) {}
void draw(){ };
private:
std::string myName;
};
Related
I have a problem with a static variable within a class.
I'm trying to edit a static variable of a child class without editing the others childs class static variable.
The header file :
class A {
public:
A() {}
void printName() {qDebug() << _name; }
void changeName(QString name) {_name = name;}
private:
static QString _name;
};
QString A::_name = QString("default");
class B : public A {
public:
B() : A() {}
};
class C : public A {
public:
C() : A() {}
};
I'm trying to edit the static _name of my class B without editing the _name of my class C. When I try this code in this main.cpp :
int main(int argc, char *argv[])
{
A *a = new B{};
A *b = new B{};
A *c = new C{};
a->printName();
b->printName();
c->printName();
B *tmp = dynamic_cast<B*>(a);
tmp->changeName("new");
qDebug() << "Then";
a->printName();
b->printName();
c->printName();
}
Here's what I have :
"default"
"default"
"default"
Then
"new"
"new"
"new"
Anyone has any idea on how I could fix this ?
Here's what I've also try :
class A {
public:
A() {}
virtual ~A() {}
void printName() {qDebug() << _name; }
virtual void changeName(QString name) {_name = name;}
private:
static QString _name;
};
QString A::_name = QString("default");
class B : public A {
public:
B() : A() {}
void changeName(QString name) override {_name = name;}
private:
static QString _name;
};
class C : public A {
public:
C() : A() {}
void changeName(QString name) override {_name = name;}
private:
static QString _name;
};
There is only one A::_name, it can only have one value at any given time. Since all your derived types uses the same static member they necessarily all have the same _name value. To fix this, each derived type must provide it's own static member instead.
To avoid repeating the same members in every derived type, you can define them in a templated intermediate class that sits between A and the derived types B and C. Each template specialization has it's own static member. So, provided each derived type supplies a unique value to the intermediate type's template argument, they will have their own names. For example, split A into two classes :
#include <iostream>
#include <string>
class A {
public:
virtual void printName() = 0;
virtual void changeName(std::string name) = 0;
};
template<class T>
class A_impl : public A
{
public:
void printName() override {
std::cout << _name << '\n';
};
void changeName(std::string name) override {
_name = std::move(name);
};
private:
static std::string _name;
};
template<class T>
std::string A_impl<T>::_name = "default";
Then each derived type should inherit from A_impl instead of A. By providing their own type to A_impl, you can be sure each derived type provides a unique template argument :
class B : public A_impl<B> { };
class C : public A_impl<C> { };
Now your test should print
default
default
default
Then
new
new
default
Is the following code the proper usage of shared_from_this - in the context of (multiple inheritance and proper reference counts)? The code is and implementation of the double dispatch visitor pattern where the interface accepts a shared pointer.
class EventIf;
typedef std::shared_ptr<EventIf> EventIfPtr;
class DispatchIF;
typedef std::shared_ptr<DispatchIF> DispatchIFPtr;
class EventOne;
typedef std::shared_ptr<EventOne> EventOnePtr;
class EventTwo;
typedef std::shared_ptr<EventTwo> EventTwoPtr;
class DispatchIF
{
public:
Dispatch(EventOnePtr pEvent){ std::cout << pEvent->GetType(); }
Dispatch(EventTwoPtr pEvent){ std::cout << pEvent->GetType() << pEvent->foo; }
};
class EventIf
{
public:
EventIf(theType) : type(theType) {}
virtual ~EventIf(){}
int GetType(){ return type; }
virtual void Accept(DispatchIFPtr pDispatcher) = 0;
protected:
int type;
};
cass EventOne : public EventIf, std::enable_shared_from_this<EventOne>
{
public:
EventOne() : EventIf(1) {}
virtual ~EventOne(){}
virtual void Accept(DispatchIFPtr pDispatcher){ pDispatcher->Dispatch(shared_from_this()); }
};
cass EventTwo : public EventIf, std::enable_shared_from_this<EventTwo>
{
public:
EventTwo() : EventIf(1) {}
virtual ~EventTwo(){}
virtual void Accept(DispatchIFPtr pDispatcher){ pDispatcher->Dispatch(shared_from_this()); }
public:
int foo;
};
I made class Head and class Derived from class Head. What should I do to have static (like a counter of object of class Head) variable which not increment in derived class.
In Head class:
class Head{
private:
static int counter;
string name;
int amount;
public:
Head(const string& n):name(n){
counter++;
}
};
int Head::counter=0;
and in class Derived:
class Derived: public Head{
public:
Derived(const string& n):Head(n){};
};
My target is to not increment counter when I create new object of class Derived.
What should I use? Virtual class, can someone explain me how to resolve this problem?
Make a conditional in your constructor (completely untested):
class Head{
private:
static int counter;
string name;
int amount;
public:
Head(const string& n, bool increment = true):name(n) {
if (increment) {
counter++;
}
}
};
int Head::counter=0;
and in class Derived:
class Derived: public Head{
public:
Derived(const string& n):Head(n, false){};
};
Segregate ctors, add another protected ctor for derived classes?
struct Base {
Base(const string &);
protected:
Base(nullptr_t, const string &);
};
struct Derived: Base {
Derived(const string &s): Base(nullptr, s) {}
};
You could just overload the constructor by changing the signature.
class Head{
private:
static int counter;
string name;
int amount;
public:
Head(){}
Head(const string& n):name(n) {count++;}
Head(const string& n,int a):name(n) {}
}
int Head::counter=0;
class Derived{
public:
Derived(const string& n):Head(n,1){};
}
I use MinGW latest version to compile the following code. I get the folowing message
y:/bbom/source/om0/basic/test.cpp: In static member function 'static void somecl
ass::init(class_object*)':
y:/bbom/source/om0/basic/test.cpp:68:50: error: no matching function for call to
'class_object::add_method(void (&)(object*, arch&))'
y:/bbom/source/om0/basic/test.cpp:68:50: note: candidate is:
y:/bbom/source/om0/basic/test.cpp:27:54: note: template<class p_function> void c
lass_object::add_method(typename p_function::funcion_type)
make.exe: *** [y:/bbom/bin/om0/basic/test.a] Error 1
Here is my code undressed from every thing not needed for this question
#include <exception>
class exception : public std::exception
{
public:
exception() {}
exception(const exception &);
~exception() throw() {}
virtual const char *what() const throw();
};
typedef unsigned id, version;
class class_object;
class object
{
public:
virtual ~object() {}
void *get_method(id);
class_object *get_class_object();
};
class class_object : public object
{
public:
template <class p_function>
void add_method(typename p_function::funcion_type p)
{add_method2((void *)p, p_function::function_id);}
void add_method2(void *, id);
};
template <typename p_func, id p_id>
class function
{
public:
typedef p_func function_type;
enum {function_id = p_id, };
function(object *p) {m_func = (p_func)p->get_method(p_id);}
p_func m_func;
};
class iface : public object
{
public:
iface(object *p) : m_object(p) {}
static void init(class_object *) {}
object *m_object;
};
class arch;
class archivable : public iface
{
public:
typedef void (*archive_func_type)(object *, arch &);
typedef function<archive_func_type, 0x5afeb287> archive_type;
archivable(object *);
archive_type archive;
};
class someclass : public object
{
public:
static void archive(object *, arch &)
{
}
static void init(class_object *p)
{
p->add_method<archivable::archive_type>(archive);
// the compiler says this call cannot be matched to
// add_method declared in class 'class_object'
}
};
What is wrong with my call to the template method in class_object::add_method<...>()
It appears you mistyped function_type as funcion_type on line 27 of test.cpp.
Typo. funcion_type should be function_type.
I have an existing project with the following class inheritance
class Base
{
public:
Base();
virtual ~Base();
void SetID(unsigned short);
virtual inline unsigned short GetID();
protected:
unsigned short id;
};
class Generic : public Base {
public:
Generic(const char *in_name);
const char* GetName() { return name; }
protected:
char name[30];
};
class Actor : public Generic
{
public:
Actor(const char *in_name);
~Actor();
void DoSomething(const char* str);
};
Now i created a separate project were i want to provide an interface that has to be implemented in order to use the functionality - i plan on reusing this project for other implementation.
class MyInterface
{
public:
virtual ~MyInterface() {}
// Our methods that need to implemented
virtual const char* GetName() = 0;
virtual void DoSomething(const char* str) = 0;
virtual unsigned short GetID() = 0;
};
Now i simply wanted to use this with my actor class e.g.
class Actor : public Generic, public MyInterface
however it fails to compile
'const char *MyInterface::GetName(void)' : is abstract see declaration of 'MyInterface::GetName'
'unsigned short MyInterface::GetID(void)' : is abstract see declaration of 'MyInterface::GetID'
error C2385: ambiguous access of 'GetName'
could be the 'GetName' in base 'Generic'
or could be the 'GetName' in base 'MyInterface'
The problem is probably that GetName is already implemented in Generic, and GetID is already implemented in Base - so in the child class Actor implementing the Interface is not possible because the compiler is not smart enough to realize there is already an implementation of these methods.
However, i found a workaround - but for this i would have to extend the header of the actor class which is not a nice thing - and i wanted to know if there is another approach - my fix is
class Actor : public Generic, public MyInterface
{
public:
Actor(const char *in_name);
~Actor();
void DoSomething(const char* str);
const char* GetName() { return Generic::GetName(); };
inline unsigned short GetID() { return Base::GetID(); };
};
Now this obviously will not work for varargs methods and i would have to implement existing methods and delegate to the parent again - is there a better solution?
EDIT For clarifications - the classes base,generic and actor exist in another project managed by others, modifications to these should be very limited. - I created a seperate project which creates a static LIB - to use functions of these in conjunction with the actor class - i created an interface to not have any dependency in my own project and also provide a reusable lib for other projects which would simply just need to implement this interface.
class Base
{
protected:
unsigned short id;
public:
void SetID(unsigned short);
virtual inline unsigned short GetID() { return id; }
virtual ~Base() {}
Base(): id() {}
};
class Generic
: public Base
{
protected:
char name[30];
public:
const char* GetName() { return name; }
Generic(const char* in_name): name() {}
};
class Actor
: public Generic
{
public:
void DoSomething(const char* str) {}
~Actor() {}
Actor(const char* in_name)
: Generic( name )
{}
};
class MyInterface
{
public:
// Our methods that need to implemented
virtual const char* name() const = 0;
virtual int id() const = 0;
virtual void doSomething( const char* str ) = 0;
virtual ~MyInterface() {}
};
template< class TpBase >
class MyInterfaceOn
: public virtual MyInterface
, public TpBase
{
public:
typedef TpBase Base;
private:
MyInterfaceOn& mutableSelf() const
{ return *const_cast<MyInterfaceOn*>( this ); }
public:
const char* name() const { return mutableSelf().Base::GetName(); }
int id() const { return mutableSelf().Base::GetID(); }
void doSomething(const char* str) { Base::DoSomething( str ); }
MyInterfaceOn( char const name[] )
: Base( name )
{}
};
class MyActor
: public MyInterfaceOn< Actor >
{
public:
MyActor( char const name[] )
: MyInterfaceOn< Actor >( name )
{}
};
int main()
{
MyInterface const& actor = MyActor( "NN" );
}