I have one Base and many (1..N) Derived classes like that:
class Base {
public:
virtual void OnMouseMove(int x, int y) = 0;
}
class Derived_1: public Base {
public:
void OnMouseMove(int x, int y) override;
}
class Derived_2: public Base {
public:
void OnMouseMove(int x, int y) override;
}
void Derived_1::OnMouseMove(int x, int y) {actions 1};
void Derived_2::OnMouseMove(int x, int y) {actions 2};
All derived classes have the same definition but different OnMouseMove() functions.
I do not like how the program looks, because I have to write in header files all the same derived functions only with different names Derived_1, Derived_2.
Is it possible to write program shorter? I need something like that:
class Derived: public Base {
public:
void OnMouseMove(int x, int y) override;
}
class Derived_1 : public Derived{};
class Derived_2 : public Derived{};
void Derived_1::OnMouseMove(int x, int y) {actions 1};
void Derived_2::OnMouseMove(int x, int y) {actions 1};
What about using templates in that case like this one:
class Base {
public:
virtual void OnMouseMove(int x, int y) = 0;
};
template < int N>
class Derived: public Base {
public:
void OnMouseMove(int x, int y) override;
};
template<> void Derived<1>::OnMouseMove(int x, int y) {std::cout<< "1"<< std::endl;}
template<> void Derived<2>::OnMouseMove(int x, int y) {std::cout<< "2"<< std::endl;}
int main()
{
Base* ptr1 = new Derived<1>;
Base* ptr2 = new Derived<2>;
ptr1->OnMouseMove(5,6);
ptr2->OnMouseMove(5,6);
}
Related
I am using CodeBlocks.
In C++, I have 3 header files and 3 cpp files like below.
Base.h
class Base
{
public:
virtual int funky(int x, int y);
};
Base.cpp
int funky(int x, int y) {
return x+y;
}
FirstClass.h
class FirstClass: public Base
{
public:
virtual int funky(int x, int y);
};
FirstClass.cpp
int funky(int x, int y) {
return x+y;
}
SecondClass.h
class SecondClass: public Base
{
public:
virtual int funky(int x, int y);
};
SecondClass.cpp
int funky(int x, int y) {
return x+y;
}
In this condition I take error of "multiple definition." But, I have to use these functions with the same names.
I tried
int funky (int x, int y) override;
but it did not work.
I need all three function, because when I want to call them like below and if they are defined like above, I cannot reach them.
vector<Base> BASE = {FirstClass(), SecondClass()};
BASE[1]->funky(1,2)
Do you have any suggestion? I am open to another approach to this problem.
Thank you.
In the above code sample, you defining funky in two different cpp files but have declared in your class. So following should be the correct format:
FirstClass.cpp
int FirstClass::funky(int x, int y) {
return x+y;
}
SecondClass.cpp
int SecondClass::funky(int x, int y) {
return x+y;
}
main.cpp
FirstClass a;
SecondClass b;
cout<<a.funky(1,2)<<" "<<b.funky(3,4)<<endl;
int funky(int x, int y) in both your .cpp files are defined as free functions that has nothing to do with the classes you've defined. They have the same signature and you therefore get a linking problem with multiple definitions.
I suggest you make the destructor in the base class virtual, just in case you want to destroy objects through a base class pointer.
Inheriting, overriding and defining the member functions could look like this:
class Base {
public:
virtual ~Base() = default; // virtual destructor
virtual int funky(int x, int y) = 0; // = 0 added to make it pure virtual
};
class FirstClass : public Base { // inherit
public:
int funky(int x, int y) override; // now you can override
};
int FirstClass::funky(int x, int y) { // class member function definition
return x+y;
}
And you need to do the same for SecondClass.
You should not use vector<Base> though. You will not store Base objects but most probably pointers to objects of types derived from Base, like FirstClass and SecondClass. I suggest using the smart pointer std::unique_ptr for this:
#include <memory>
int main() {
std::vector<std::unique_ptr<Base>> BASE;
BASE.emplace_back(std::make_unique<FirstClass>());
BASE.emplace_back(std::make_unique<SecondClass>());
std::cout << BASE[0]->funky(2,3) << '\n';
std::cout << BASE[1]->funky(2,3) << '\n';
}
Demo
I have the following code:
class A
{
public:
virtual void f(int a) = 0;
virtual void f(int a, int b) = 0;
};
class B : public A
{
public:
// do not want f(int a,int b) accessible
void f(int a);
};
class C : public A
{
public:
// do not want f(int a) accessible
void f(int a, int b);
};
I am aware that purely virtual functions cannot be deleted. Is there any way to disable these functions such that a compile time error occurs if an instance of B tries to call f(int,int) or when an instance of C tries to call f(int)
There's no way to do that. You'd need a more complex class hierarchy. Something like this:
class A
{
public:
virtual ~A() {}
};
class BaseForB : public A
{
public:
virtual void f(int a) = 0;
};
class BaseForC : public A
{
public:
virtual void f(int a, int b) = 0;
};
class B : public BaseForB
{
public:
void f(int a) override
{
// details...
}
};
class C : public BaseForC
{
public:
void f(int a, int b) override
{
// details...
}
};
One option is to put a class between A B and A which implements a private version of the function that is final and not callable by instances of B like this:
class A
{
public:
virtual void f(int a) = 0;
virtual void f(int a, int b) = 0;
};
class A_B : public A {
using A::f;
private:
void f(int a, int b) final override {}
};
class B : public A_B
{
public:
// do not want f(int a,int b) accessible
void f(int a);
};
I have two classes with same interface methods:
struct ImplGenerated {
int foo(int x, int y);
void bar(double x);
....
};
struct ImplCustom {
int foo(int x, int y);
void bar(double x);
.....
};
And class Wrapper:
struct Wrapper {
Wrapper(ImplGenerated * i): m_generated(i), m_custom(0) {}
Wrapper(ImplCustom * i): m_generated(0), m_custom(i) {}
int foo(int x, int y);
void bar(double x);
....
private:
??? getImpl();
ImplGenerated * m_generated;
ImplCustom * m_custom;
};
int Wrapper::foo(int x, int y) {
return getImpl()->foo(x, y);
}
void Wrapper::bar(double x) {
getImpl()->bar(x);
}
Is it possible to write some C++ construction (class or any other, but not macros) instead getImpl() for resolving current implementation object and call corresponding method?
like this:
???? getImpl() {
return m_custom ? m_custom : m_generated;
}
Note:
Only changes to ImplCustom could be applied (add base class or make template or something else), ImplGenerated is auto-generated by external project therefore couldn't be changed (add base class is impossible).
Wrapper could not be template, because is interface class.
Update:
It is impossible to derive ImplCustom from ImplGenerated.
The solution I see here is to create a wrapper
The goal of this solution is to generate an interface for your two unrelated classes.
Let's start by making a Base classe:
struct ImplInterface {
virtual int foo(int x, int y) = 0;
virtual void bar(double x) = 0;
// ...
};
Now you can create wrapper for each Impl you got:
struct GeneratedWrapper : ImplInterface {
virtual int foo(int x, int y) {
_impl.foo(x, y);
}
virtual void bar(double x) {
_impl.bar(x);
}
private:
ImplGenerated _impl;
};
struct CustomWrapper : ImplInterface {
virtual int foo(int x, int y) {
_impl.foo(x, y);
}
virtual void bar(double x) {
_impl.bar(x);
}
private:
ImplCustom _impl;
};
Now you can use these wrapper like this:
ImplInterface* wrapper = new GeneratedWrapper(implGenerated);
This method could be much shorter using templates, let's make One wrapper for your new interface:
template<typename T>
struct EveryImplWrapper : ImplInterface {
virtual int foo(int x, int y) {
_impl.foo(x, y);
}
virtual void bar(double x) {
_impl.bar(x);
}
private:
T _impl;
};
Now you can use it like this:
ImplInterface* = new EveryImplWrapper<ImplCustom>(implCustom);
If you can't modify the existing classes, you can still add a facade to provide post-hoc polymorphism. That is:
Wrapper could not be template, because is interface class
is only partly true. You can have a non-templated interface (ABC) and a templated concrete subclass.
// publically visible parts
struct ImplInterface {
virtual ~ImplInterface() {}
virtual int foo(int x, int y) = 0;
virtual void bar(double x) = 0;
....
};
struct Wrapper {
// ...
ImplInterface *Wrapper::getImpl();
// ... do you want to keep the same impl selection across calls?
ImplInterface *m_impl;
};
// implementation details can be hidden in a cpp file
template <typename RealImpl>
struct ImplFacade: ImplInterface {
RealImpl pimpl_;
explicit ImplFacade(RealImpl *impl) : pimpl_(impl) {}
int foo(int x, int y) override { return pimpl_->foo(x,y); }
void bar(double x) override { pimpl_->bar(x); }
};
ImplInterface *Wrapper::getImpl() {
if (!m_impl) {
if (m_custom)
m_impl = new ImplFacade<ImplCustom>(m_custom);
else
m_impl = new ImplFacade<ImplGenerated>(m_generated);
}
return m_impl;
}
Ideally you should be using unique_ptr for the new member in real code.
If you can use the c++11 Standard you can use std::function to accomplish this:
struct Wrapper {
Wrapper(ImplGenerated * i):
foo(std::bind(&ImplGenerated::foo, i)),
bar(std::bind(&ImplGenerated::bar, i)) {}
Wrapper(ImplCustom * i):
foo(std::bind(&ImplCustom ::foo, i)),
bar(std::bind(&ImplCustom ::bar, i)) {}
//Now the functions are member variables but it works the same way
std::function<int(int x, int y)> foo;
std::function<void(double x)> bar;
....
//If you don't Need to destruct the impl-objects then you don't even Need to store them
};
I believe what you're wanting is to use inheritance / interface:
struct ImplInterface {
virtual int foo(int x, int y) = 0;
virtual void bar(double x) = 0;
....
};
struct ImplGenerated : public ImplInterface {
virtual int foo(int x, int y);
virtual void bar(double x);
....
};
struct ImplCustom : public ImplInterface {
virtual int foo(int x, int y);
virtual void bar(double x);
.....
};
now your getImpl() will return a ImplInterface*
Or if you can't add a base class, then in your Wrapper class instead of getImpl() do this:
int foo(int x, int y)
{
if (m_generated != nullptr)
{
return m_generated->foo(x,y);
}
else if (m_custom != nullptr)
{
return m_custom->foo(x, y);
}
throw "hey dude!";
}
I know it's a lot of work, but hey you've no base class to work with.
This simple example demonstrates the C++ syntax for calling base class constructors - as far as I understand it as a C++ learner:
class BaseClass {
protected:
int i;
public:
BaseClass(int x) {
i = x;
}
};
class DerivedClass: public BaseClass {
int j;
public:
DerivedClass(int x, int y): BaseClass(y) {
j = x;
}
Here, the base class constructor can take named arguments to the derived class constructor as input.
Now, what if I want to call BaseClass() constructor with an input value that is not a direct input to DerivedClass()? Basically, I'd like to do some multiline work with x and y within DerivedClass(), then pass a calculated value to BaseClass(). Can this be done with constructors? Should this be done with some kind of initializer method instead?
You can do that, yes:
class BaseClass
{
public:
BaseClass(int x) : i(x) {}
private:
int i;
};
class DerivedClass: public BaseClass
{
public:
DerivedClass(int x, int y):
BaseClass(compute(x, y)), // Neither i or j are initialized here yet
j(x)
{}
private:
static int compute(int a, int b) { return a + b; } // Or whatever
int j;
};
Note that you can even make compute() a non-static method but be aware that DerivedClass or BaseClass members won't be initialized at the time of the call. So you won't be able to rely on their values.
If you're using C++11 or newer you can also use lambda expressions:
class BaseClass
{
public:
BaseClass(int x) : i(x) {}
private:
int i;
};
class DerivedClass: public BaseClass
{
public:
DerivedClass(int x, int y): BaseClass(
[=]()->int
{
int sum = 0;
for(int i = 0; i < x; ++i)
{
sum += y + i * x;
}
return sum;
}()), j(x)
{}
private:
int j;
};
Then you can do this:
DerivedClass(int x, int y): BaseClass(compute(x,y)), j(y) {
//j = x; //use member-initialization-list ---> ^^^^
}
int compute(int x, int y)
{
//your code
}
For the below code snippet, how do I initialize instances of class Enemy with variables (such as x, y, type)? I have it working correctly, it triggers the instances no matter how many of them I insert... I just need to know the best way of creating an enemy with certain variables that will differ for each of my instances... particularly when some of those variables are in the base class and others are not.
class BaseObject
{
public:
virtual void Render() = 0;
int x;
int y;
};
class Enemy : public BaseObject
{
public:
Enemy() { }
virtual void Render()
{
cout << "Render! Enemy" << endl;
}
typedef std::set<BaseObject *> GAMEOBJECTS;
GAMEOBJECTS g_gameObjects;
int main()
{
g_gameObjects.insert(new Enemy());
g_lootObjects.insert(new Loot());
for(GAMEOBJECTS::iterator it = g_gameObjects.begin();
it != g_gameObjects.end();
it++)
{
(*it)->Render();
}
for(GAMEOBJECTS::iterator it = g_lootObjects.begin();
it != g_lootObjects.end();
it++)
{
(*it)->Render();
}
return 0;
}
Include the arguments in the enemy constructor and Base constructors. You can then use those to initialize the member variables.
class BaseObject
{
public:
BaseObject(int x, int y) : x(x), y(y){ }
virtual void Render() = 0;
int x;
int y;
};
and
class Enemy : public BaseObject
{
public:
Enemy(int x, int y, int foo) : BaseObject(x,y), foo(foo) { }
int foo;
...
};