Hello I'm studying c++ language and I'm really wondering that if use object Pointer with dynamic array. Weapon class is derived by CItem class. At this time I'm typing like this.
CItem* pItem = new cWeapon[m_size];
and I doing initialize each object like this
pItem[0].initialize();
pItem[1].initialize();
pItem[2].initialize();
pItem[3].initialize();
....
pItem[n].initialize();
However this time make problem. Size is different pItem and cWeapon. Because Pointer Operation cause error.
and I wondering that how solve this problem?
sorry about my fool English skill.
Example code:
#include <iostream>
#include <memory>
#include <vector>
class BaseItem // abstract class
{
public:
virtual void initialize() = 0; // pure virtual function (no implementation)
};
class Sword : public BaseItem
{
public:
void initialize() override
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
class Shield : public BaseItem
{
public:
void initialize() override
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main()
{
std::vector<std::unique_ptr<BaseItem>> items;
items.emplace_back(new Sword);
items.emplace_back(new Sword);
items.emplace_back(new Shield);
items.emplace_back(new Sword);
items.emplace_back(new Shield);
for(auto& element : items)
{
element->initialize();
}
return 0;
}
You can run it here: wandbox.org
Output:
virtual void Sword::initialize()
virtual void Sword::initialize()
virtual void Shield::initialize()
virtual void Sword::initialize()
virtual void Shield::initialize()
In this implementation I used std::vector for dynamic arrays. Vector is containing types of smart pointer to BaseItem. In this case smart pointer is std::unique_ptr it helps a lot with resource management and it is easy to use. Without it you need manually delete all elements from vector. I really recomend using it.
Our BaseItem now can provide "interface" that we want to implement in any other class. If you don't want to force class to implement such method just don't make it pure virtual (remove = 0 and add {} body of function)
More information about:
C++ Abstract Class
__PRETTY_FUNCTION__
C++ virtual functions
C++ inheritance
This is kind of "old" approach. You can read also about composition and entity system (ES).
Related
I am fairly new to C++ and templates. I dont expect the reason why it doesnt work to be very complex, but I'm just not getting it.
void print(vector<> v) {
return;
}
does not compile with the error
error: wrong number of template arguments (0, should be at least 1)
however
void print(vector<int> v) {
return;
}
doesn't yield such an error.
Why is that?
You must make your function template to accept more than one type:
template <typename T>
void print(vector<T> v) {
return;
}
If you are coming from another language (I think Java uses the syntax you proposed?), I suggest getting a good C++ book to learn from. It's going to be much less painful to learn properly from start than trying to apply your knowledge from other languages in C++.
If you need to store elements of different types, you should look into polymorphism and class hierarchies. For example, if you had two different classes A and B, and needed a vector to hold either of those, you could make sure that they share a common base class.
You could then store pointers or references to such objects in one and the same vector, like so (using smart pointers in this case):
#include <iostream>
#include <memory>
#include <vector>
class Base {
public:
virtual ~Base() {}
virtual void print() = 0;
};
using BasePtr = std::shared_ptr<Base>;
class A : public Base {
public:
virtual void print() override { std::cout << "I'm an A" << std::endl; }
};
class B : public Base {
public:
virtual void print() override { std::cout << "I'm a B" << std::endl; }
};
void print(const std::vector<BasePtr>& v) {
for (auto&& i : v)
i->print();
}
int main()
{
std::vector<BasePtr> v;
v.push_back(std::make_shared<A>()); /* create and add an element of type A */
v.push_back(std::make_shared<B>()); /* create and add an element of type B */
print(v);
}
(Also, note that I'm passing the vector type as const reference, otherwise it would be copied before being passed into the function.)
I need to store a container of pointers to objects.
These objects have some common methods/attributes (interface) that I want to enforce (possibly at compile time) and use.
Example:
struct A{
void fly(){}
};
struct B{
void fly(){}
};
A a;
B b;
std::vector<some *> objects;
objects.push_back(&a);
objects.push_back(&b);
for(auto & el: objects)
el->fly();
The simpler solution would be A and B inherit a common base class like FlyingClass:
struct FlyingClass{
void fly(){}
};
struct A: public FlyingClass { ...
struct B: public FlyingClass { ...
and create a
std::vector<FlyingClass *> objects;
This will work and also enforce the fact that I can only add to objects things that can fly (implement FlyingClass).
But what if I need to implement some other common methods/attributes WITHOUT coupling them with the above base class?
Example:
struct A{
void fly(){}
void swim(){}
};
struct B{
void fly(){}
void swim(){}
};
And i would like to do:
for(auto & el: objects) {
el->fly();
...
el->swim();
...
}
More in general i would be able to call a function passing one of these pointers and access both the common methods/attributes, like:
void dostuff(Element * el){
el->fly();
el->swim();
}
I could try to inherit from another interface like:
struct SwimmingClass{
void swim(){}
};
struct A: public FlyingClass, public SwimmingClass { ...
struct B: public FlyingClass, public SwimmingClass { ...
But then what the container should contain?
std::vector<FlyingClass&&SwimmingClass *> objects;
Sure, i could implement SwimmingFlyingClass, but what if i need RunningClass etc.. This is going to be a nightmare.
In other words, how can I implement a pointer to multiple interfaces without coupling them?
Or there is some template way of rethinking the problem?
Even run time type information could be acceptable in my application, if there is an elegant and maintainable way of doing this.
It is possible to do this, in a pretty TMP-heavy way that's a little expensive at runtime. A redesign is favourable so that this is not required. The long and short is that what you want to do isn't possible cleanly without language support, which C++ does not offer.
As for the ugly, shield your eyes from this:
struct AnyBase { virtual ~AnyBase() {} }; // All derived classes inherit from.
template<typename... T> class Limited {
AnyBase* object;
template<typename U> Limited(U* p) {
static_assert(all<is_base_of<T, U>...>::value, "Must derive from all of the interfaces.");
object = p;
}
template<typename U> U* get() {
static_assert(any<is_same<U, T>...>::value, "U must be one of the interfaces.");
return dynamic_cast<U*>(object);
}
}
Some of this stuff isn't defined as Standard so I'll just run through it. The static_assert on the constructor enforces that U inherits from all of T. I may have U and T the wrong way round, and the definition of all is left to the reader.
The getter simply requires that U is one of the template arguments T.... Then we know in advance that the dynamic_cast will succeed, because we checked the constraint statically.
It's ugly, but it should work. So consider
std::vector<Limited<Flying, Swimming>> objects;
for(auto&& obj : objects) {
obj.get<Flying>()->fly();
obj.get<Swimming>()->swim();
}
You are asking for something which doesn't make sense in general, that's why there is no easy way to do it.
You are asking to be able to store heterogeneus objects in a collection, with interfaces that are even different.
How are you going to iterate over the collections without knowing the type? You are restricted to the least specific or forced to do dynamic_cast pointers and cross fingers.
class Entity { }
class SwimmingEntity : public Entity {
virtual void swim() = 0;
}
class FlyingEntity : public Entity {
virtual void fly() = 0;
}
class Fish : public SwimmingEntity {
void swim() override { }
}
class Bird : public FlyingEntity {
void fly() override { }
}
std:vector<Entity*> entities;
This is legal but doesn't give you any information to the capabilities of the runtime Entity instance. It won't lead anywhere unless you work them out with dynamic_cast and rtti (or manual rtti) so where's the advantage?
This is pretty much a textbook example calling for type erasure.
The idea is to define an internal abstract (pure virtual) interface class that captures the common behavior(s) you want, then to use a templated constructor to create a proxy object derived from that interface:
#include <iostream>
#include <vector>
#include <memory>
using std::cout;
struct Bird {
void fly() { cout << "Bird flies\n"; }
void swim(){ cout << "Bird swims\n"; }
};
struct Pig {
void fly() { cout << "Pig flies!\n"; }
void swim() { cout << "Pig swims\n"; }
};
struct FlyingSwimmingThing {
// Pure virtual interface that knows how to fly() and how to swim(),
// but does not depend on type of underlying object.
struct InternalInterface {
virtual void fly() = 0;
virtual void swim() = 0;
virtual ~InternalInterface() { }
};
// Proxy inherits from interface; forwards to underlying object.
// Template class allows proxy type to depend on object type.
template<typename T>
struct InternalImplementation : public InternalInterface {
InternalImplementation(T &obj) : obj_(obj) { }
void fly() { obj_.fly(); }
void swim() { obj_.swim(); }
virtual ~InternalImplementation() { }
private:
T &obj_;
};
// Templated constructor
template<typename T>
FlyingSwimmingThing(T &obj) : proxy_(new InternalImplementation<T>(obj))
{ }
// Forward calls to underlying object via virtual interface.
void fly() { proxy_->fly(); }
void swim() { proxy_->swim(); }
private:
std::unique_ptr<InternalInterface> proxy_;
};
int main(int argc, char *argv[])
{
Bird a;
Pig b;
std::vector<FlyingSwimmingThing> objects;
objects.push_back(FlyingSwimmingThing(a));
objects.push_back(FlyingSwimmingThing(b));
objects[0].fly();
objects[1].fly();
objects[0].swim();
objects[1].swim();
}
The same trick is used for the deleter in a shared_ptr and for std::function. The latter is arguably the poster child for the technique.
You will always find a call to "new" in there somewhere. Also, if you want your wrapper class to hold a copy of the underlying object rather than a pointer, you will find you need a clone() function in the abstract interface class (whose implementation will also call new). So these things can get very non-performant very easily, depending on what you are doing...
[Update]
Just to make my assumptions clear, since some people appear not to have read the question...
You have multiple classes implementing fly() and swim() functions, but that is all that the classes have in common; they do not inherit from any common interface classes.
The goal is to have a wrapper object that can store a pointer to any one of those classes, and through which you can invoke the fly() and swim() functions without knowing the wrapped type at the call site. (Take the time to read the question to see examples; e.g. search for dostuff.) This property is called "encapsulation"; that is, the wrapper exposes the fly() and swim() interfaces directly and it can hide any properties of the wrapped object that are not relevant.
Finally, it should be possible to create a new otherwise-unrelated class with its own fly() and swim() functions and have the wrapper hold a pointer to that class (a) without modifying the wrapper class and (b) without touching any call to fly() or swim() via the wrapper.
These are, as I said, textbook features of type erasure. I did not invent the idiom, but I do recognize when it is called for.
I have a few classes, ObjDef, PeopDef, NpcDef, and PlyDef, such that PlyDef and NpcDef each seperately inherit PeopDef, and PeopDef inherits ObjDef. Each class has functionality that builds on the class before it, so it's important that PeopDef::Tick is called before ObjDef::Tick. I have every object stored in a vector<ObjDef> object, but when the main tick loop goes through them, I want them to call the original classes' Tick, rather than ObjDef::Tick, which is what the vector<ObjDef> currently makes it do. Is there any way to do this, or do I have to have a separate vector for each class?
You can store an ObjDef pointer (ObjDef* or a smart pointer) in the vector and make the Tick method virtual.
Here's an example:
#include <iostream>
#include <vector>
#include <memory>
class ObjDef
{
public:
virtual void Tick()
{
std::cout << "ObjDef::Tick\n";
}
};
class PeopDef : public ObjDef
{
public:
virtual void Tick()
{
std::cout << "PeopDef::Tick\n";
}
};
int main()
{
std::vector<std::shared_ptr<ObjDef>> objects;
std::shared_ptr<ObjDef> obj(new ObjDef());
std::shared_ptr<ObjDef> peop(new PeopDef());
objects.push_back(obj);
objects.push_back(peop);
for (auto object : objects)
{
object->Tick();
}
return 0;
}
I'm trying to implement an event manager based on the linked code in the top answer here:
Game Objects Talking To Each Other
However I'm getting an error when I try to register the callbacks.
I'm sure it has to do with the typedef, and I admit I'm not sure how it works exactly, but it is in the exact same form in the linked code.
The B class should be inherriting from the Interface, so why is the type different?
I've condensed the code into the smallest example below.
#include <iostream>
class Interface;
typedef void (Interface::*Callback)(void *data);
class Interface
{
public:
void Register (Callback func);
};
void Interface::Register(Callback func)
{
std::cout << "Register" << std::endl;
}
class B : public Interface
{
public:
B();
void Echo(void *data);
};
B::B()
{
Register( (Callback)Echo );
}
void B::Echo(void *data)
{
std::cout << "Echo" << std::endl;
}
int main()
{
B b;
return 0;
}
Here's the error I get under g++ 4.6.1:
test.cpp: In constructor ‘B::B()’:
test.cpp:31:22: error: argument of type ‘void (B::)(void*)’ does not match ‘Callback {aka void (Interface::*)(void*)}’
Could anyone please explain what I'm doing wrong?
Thanks
As #Kerrek correctly pointed out, Echo is not a member of Interface, therefore B::Echo doesn't qualify as Interface::*Callback. But you can use a template to accomplish that, e.g.:
template <class T> class Interface {
public:
typedef void (T::*Callback)(void *data);
void Register(Callback func) {
std::cout << "Register" << std::endl;
}
// ...
};
class B : public Interface<B> {
public:
B() {
Register(&B::Echo);
}
void Echo(void *data) {
// Do something
}
};
I think you might be better off using std::function (c++11) or boost::function (c++03+boost)
#include <iostream>
class Interface;
typedef void (Interface::*Callback)(void *data);
class Interface
{
public:
std::function<void(void*)> register;
Interface(std::function<void(void*)> register_)
: register(register_) //intializer list
{}
virtual ~Interface(){} //put me in
};
void Interface::Register(Callback func)
{
std::cout << "Register" << std::endl;
}
class B : public Interface
{
public:
B();
void Echo(void *data);
};
B::B()
: Interface( std::bind(B::Echo, this) )
{}
void B::Echo(void *data)
{
std::cout << "Echo" << std::endl;
}
Although why you aren't using pure virtuals is beyond me
class Interface
{
public:
virtual void Echo(void*)=0;
};
void B::Echo(void *data) //implements Echo
{
std::cout << "Echo" << std::endl;
}
call interface->echo will call the child
if you need performance then use the
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
And be very careful with void* they are generally considered bad.
EDIT ADDRESSING POINT IN COMMENTS: non pure virtuals
class Interface
{
public:
virtual ~Interface(){} //put me in
virtual void echo(void*){} //if implementation is not extended it will do nothing.
//others
};
This ins't Java, interfaces aren't a thing defined by the language. This way you can have an interface which you can pick can choose which part to implement, if a callback doesn't concern your class, then just don't implement it.
void* are bad for a whole host of reasons. from C++ FAQ
avoid void* (keep them inside low-level functions and data structures
if you really need them and present type safe interfaces, usually
templates, to your users)
http://www2.research.att.com/~bs/bs_faq.html
search on "void*"
but basically void* bypass all the type safety that C++ went out of it's way adding. It is a hack in C to make up for the fact that it doesn't have any polymorphism or generic code.
What are the ways in C++ to handle a class that has ownership of an instance of another class, where that instance could potentially be of a number of classes all of which inherit from a common class?
Example:
class Item { //the common ancestor, which is never used directly
public:
int size;
}
class ItemWidget: public Item { //possible class 1
public:
int height;
int width;
}
class ItemText: public Item { //possible class 2
std::string text;
}
Let's say there is also a class Container, each of which contains a single Item, and the only time anyone is ever interested in an Item is when they are getting it out of the Container. Let's also say Items are only created at the same time the Container is created, for the purpose of putting them in the Container.
What are the different ways to structure this? We could make a pointer in Container for the contained Item, and then pass arguments to the constructor of Container for what sort of Item to call new on, and this will stick the Items all in the heap. Is there a way to store the Item in the stack with the Container, and would this have any advantages?
Does it make a difference if the Container and Items are immutable, and we know everything about them at the moment of creation, and will never change them?
A correct solution looks like:
class Container {
public:
/* ctor, accessors */
private:
std::unique_ptr<Item> item;
};
If you have an old compiler, you can use std::auto_ptr instead.
The smart pointer ensures strict ownership of the item by the container. (You could as well make it a plain pointer and roll up your own destructor/assignment op/copy ctor/move ctor/ move assignment op/ etc, but unique_ptr has it all already done, so...)
Why do you need to use a pointer here, not just a plain composition?
Because if you compose, then you must know the exact class which is going to be composed. You can't introduce polymorphism. Also the size of all Container objects must be the same, and the size of Item's derived classes may vary.
And if you desperately need to compose?
Then you need as many variants of Container as there are the items stored, since every such Container will be of different size, so it's a different class. Your best shot is:
struct IContainer {
virtual Item& getItem() = 0;
};
template<typename ItemType>
struct Container : IContainer {
virtual Item& getItem() {
return m_item;
}
private:
ItemType m_item;
};
OK, crazy idea. Don't use this:
class AutoContainer
{
char buf[CRAZY_VALUE];
Base * p;
public:
template <typename T> AutoContainer(const T & x)
: p(::new (buf) T(x))
{
static_assert(std::is_base_of<Base, T>::value, "Invalid use of AutoContainer");
static_assert(sizeof(T) <= CRAZY_VAL, "Not enough memory for derived class.");
#ifdef __GNUC__
static_assert(__has_virtual_destructor(Base), "Base must have virtual destructor!");
#endif
}
~AutoContainer() { p->~Base(); }
Base & get() { return *p; }
const Base & get() const { return *p; }
};
The container requires no dynamic allocation itself, you must only ensure that CRAZY_VALUE is big enough to hold any derived class.
the example code below compiles and shows how to do something similar to what you want to do. this is what in java would be called interfaces. see that you need at least some similarity in the classes (a common function name in this case). The virtual keyword means that all subclasses need to implement this function and whenever that function is called the function of the real class is actually called.
whether the classes are const or not doesn't harm here. but in general you should be as const correct as possible. because the compiler can generate better code if it knows what will not be changed.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class outputter {
public:
virtual void print() = 0;
};
class foo : public outputter {
public:
virtual void print() { std::cout << "foo\n"; }
};
class bar : public outputter {
public:
virtual void print() { std::cout << "bar\n"; }
};
int main(){
std::vector<outputter *> vec;
foo *f = new foo;
vec.push_back(f);
bar *b = new bar ;
vec.push_back(b);
for ( std::vector<outputter *>::iterator i =
vec.begin(); i != vec.end(); ++i )
{
(*i)->print();
}
return 0;
}
Output:
foo
bar
Hold a pointer (preferably a smart one) in the container class, and call a pure virtual clone() member function on the Item class that is implemented by the derived classes when you need to copy. You can do this in a completely generic way, thus:
class Item {
// ...
private:
virtual Item* clone() const = 0;
friend Container; // Or make clone() public.
};
template <class I>
class ItemCloneMixin : public Item {
private:
I* clone() const { return new I(static_cast<const I&>(*this); }
};
class ItemWidget : public ItemCloneMixin<ItemWidget> { /* ... */ };
class ItemText : public ItemCloneMixin<ItemText> { /* ... */ };
Regarding stack storage, you can use an overloaded new that calls alloca(), but do so at your peril. It will only work if the compiler inlines your special new operator, which you can't force it to do (except with non-portable compiler pragmas). My advice is that it just isn't worth the aggravation; runtime polymorphism belongs on the heap.