Are there any system of classe reference in D? To be more accurate I look for the equivalent of the Delphi
TMyClassRef = class of TMyClass;
This would be used for a factory (just like in the Object but without using the class name):
// ideally
void AddNew(*TBaseClass APtr, /*?class_ref_type?*/ AClassType)
{
*APtr = new AClassType;
}
Currently I do this:
void AddNew(*TBaseClass APtr)
{
*APtr = new typeof(*APtr);
}
But the problem is that typeof() returns always TBaseClass and never a sub class of TBaseClass (when a sub class is passed as parameter). This is clearly a case where class references would be used in Delphi but the D language doesn't seem to have such a system.
Maybe I'm completely missing the idea in Delphi, but this seems to be what a templates are for:
import std.stdio;
class Parent {
string inherited() {
return "Hello from parent";
}
override string toString() {
return "Hello from parent";
}
}
class Child : Parent {
override string toString() {
return "Hello from child";
}
}
void add(C, P)(P* ptr) {
*ptr = new C;
}
void main() {
Parent t;
writeln(t); // prints null
add!Child(&t);
writeln(t); // prints Hello from child
writeln(t.inherited()); // prints Hello from parent
}
This way you pass in the type you want to instantiate instead of an instantiated object of that type. This should generate compile errors if C is not a child of P in add().
Edit:
If you want to be more specific with add, you could do this:
void add(T : Parent)(Parent* ptr) {
*ptr = new T;
}
To make things nicer, use an out parameter to be more idiomatic:
void add(T : Parent)(out Parent ptr) {
ptr = new T;
}
void main() {
Parent p;
add!Child(p);
}
D has no class references in the Delphi way as far as I have understood Delphi concept. If you need to make a run-time decision about object construction, object.TypeInfo may help you.
You can retrieve TypeInfo for a variable via typeid construct:
import std.stdio;
class Base
{
void f()
{
writeln("Base");
}
}
class Descendant : Base
{
override void f()
{
writeln("Descendant");
}
}
Base makeNew(Base other)
{
// cast is needed because create() returns plain Object
// we can be sure it is Base at least, though, because it was crated from Base
return cast(Base)typeid(other).create();
}
void main()
{
Descendant source = new Descendant;
Base target = makeNew(source);
// prints "Descendant"
target.f();
}
Is this code sample similar to what you want?
D generally has a very clear differentiation between run-time actions and compile-time ones. typeof works on compile-time and thus can't query "real" class type in case of hierarchies.
Related
Hello everyone and thanks for reading,
I'm new to working with classes and I've ran into an issues with making array's of objects,
I have a base class, and an array of the same type, I'd like to know if it's a possibility to
make subclasses of the base class type and put them into an array and call methods that're not
in the base class, sorry if this is a bad question and my apologies if my wording is off,
#include <iostream>
int main()
{
BaseClass* ObjectList[10];
ObjectList[0] = new SubClass;
ObjectList[0]->Load(10);
ObjectList[0]->OtherFunction(); // How Can I Do This?
return 0;
}
class BaseClass
{
public:
virtual void Load(int Num) = 0;
};
class SubClass : public BaseClass
{
void Load(int Num) override
{
std::cout << Num << std::flush;
}
void OtherFunction()
{
// Do Something
}
};
Thanks
Edit -
My intent is to have a simple base class with dozens and dozens of subclasses with different methods, and have an array of the base class,
You can always have more than one pointer (or reference) to the same object.
int main()
{
BaseClass* ObjectList[10];
SubClass TheSubclass;
ObjectList[0] = &TheSubclass;
ObjectList[0]->Load(10); // presumably in a loop
TheSubclass.OtherFunction();
return 0;
}
You will have to downcast your pointer to the real class (or at least a class having the method). You can use either a static_cast if you do not need any control, or a dynamic_cast if you want a run-time validation of the cast:
...
SubClass *psc = dynamic_cast<SubClass *>(ObjectList[0]);
if (psc != nullptr) { // an invalid cast would set it to NULL
psc->OtherFunction();
}
else {
// process the error
}
Coming from the Java/PHP world, I am still new to C++. Some simple things to do in other languages are a bit trickier to do in C++.
My main issue is the following. Right now, I have a class (ie. "Something") for which the constructor is injected with a virtual class dependency (ie. a children of "Base"). Then, the constructor stores this injected instance in a unique_ptr<Base> class field (using the clone idiom). This works well at the application level, everything seems to works as expected. Here is the sample code:
class Base {
public:
virtual std::unique_ptr<Base> clone() = 0;
virtual void sayHello() const = 0;
};
class Something {
public:
explicit Something(Base &base) { this->base = base.clone(); }
void sayHello() const { base->sayHello(); }
private:
std::unique_ptr<Base> base;
};
But to make sure it does, I wrote unit tests to test its behavior. In those tests, I want to assert the injected dependencies methods are actually called. So logically, injecting a "spy" dependency should do the trick.
Here is what I did at first:
class SpyDerived : public Base {
public:
explicit SpyDerived() = default;
SpyDerived(const SpyDerived &original) { this->someState = original.someState; }
std::unique_ptr<Base> clone() override { return std::make_unique<SpyDerived>(*this); }
void sayHello() const override { std::cout << "My state: " << someState << std::endl; }
void setSomeState(bool value) { this->someState = value; }
private:
bool someState = false;
};
This is the main function I use to this this out:
int main() {
SpyDerived derived;
Something something(derived);
derived.setSomeState(true);
something.sayHello();
}
For obvious reasons, someState value on print is always false. I get that the Derived instances in Something is a new copy of Derived and no longer the one that was created in the main function.
So basically, what I am trying to achieve here is to have the Something class always use the SpyDerived instance created in the main function. Is there any way I could make this work. I am trying to avoid changing the design just for test purposes.
I am using MSVC 2015 to compile the code. Keep in mind that smart pointers, C++ idioms, copy/move constructors are fairly new concepts for me.
Thanks for your help.
Well, do you want to clone your instance, or simply reference that instance?
The clone idiom is made to copy the instance of a class, making the new instance independent of the old instance.
You are basically making this, in term of PHP:
<?php
interface Base {
public function sayHello();
}
class SpyDerived implements Base {
private $someState = false;
public function sayHello() {
echo 'My state: ' . $this->someState;
}
}
class Something {
public __construct(Base $base) { $this->base = clone $base; }
public function sayHello() { $this->base->sayHello(); }
private $base = null;
}
$derived = new SpyDerived;
$something = new Something($derived);
$derived->setSomeState(true);
$something->sayHello();
?>
You see this? $base is cloned. Something::$base is a copy.
So in PHP, what would you do to solve that problem?
Simple! Remove that clone, no copies!
Well, in C++, this is the same thing. If you have an object pointer and don't want to clone it, don't actually call the clone method.
We will change your class to, like PHP, contain a reference to the object. We will start by making Something contain a non owning reference:
class Something {
public:
explicit Something(Base& b) : base{b} { }
void sayHello() const { base.sayHello(); }
private:
// we simply contain a reference to the base
Base& base;
};
In C++, a reference does not own the object. If the object is destroyed, all reference pointing to that object will point to a dead object.
As you can notice, your tests stays the same and work:
int main() {
SpyDerived derived;
Something something(derived);
derived.setSomeState(true);
something.sayHello();
}
If you want Something be the owner of Base, then use std::unique_ptr<Base>:
class Something {
public:
explicit Something(std::unique_ptr<Base> b) : base{std::move(b)} { }
void sayHello() const { base->sayHello(); }
private:
std::unique_ptr<Base> base;
};
Beware that the ownership of base should be transferred from the caller to the something class. That transfer is express through that std::move thing, because we are moving the ownership of that resource.
Then in your tests:
int main() {
auto derived = std::make_unique<SpyDerived>();
// We want to keep a non-owning reference of derived
// The star (*) operator of std::unique_ptr returns a reference to the pointed object
auto& derived_ref = *derived;
// We transfer the ownership of derived to the `Something`
Something something(std::move(derived));
// Since derived is a reference to the object pointed by our pointer,
// It will affect the value we found in `Something`, because they are
// both pointing to the same instance.
derived.setSomeState(true);
something.sayHello();
}
Since Something is owner of derived, the non-owning reference derived_ref will point to a dead object if something dies before.
I have two classes deriving from the same base class. on compile time it is known which one gets created based on a macro define. I have another class that is a user and calls member functions (different ones for each class). It looks like this:
class User() {
void useClass( Base* p ) {
#ifdef useA
p->aFun();
#else
p->bFun()
#endif
}
class Base() {}
class A : public Base {
void aFun();
}
class B : public Base {
void bFun();
}
class C {
C() {
#ifdef useA
p = new A();
#else
p = new B();
#endif
}
Base* p;
User m_user;
void doStuffWithUser() {
user.useClass( p );
}
}
I would like to reduce the amount of macros, so I am wondering if there is a better way to do this. In particular, the #ifdef in the User class doesn't look very nice to me. Is there a way to reproduce it without using the macro? Ideally without runtime checks to determine what type p is.
EDIT:
The two derived classes have different members that need to be called and despite the inheritance, this cant be changed.
A solution is the visitor pattern.
The idea is to have two classes : the visitor and the visited.
The visitor is used to call a function depending on the real type of the object. The visited is the object of your class hierarchy.
In your example, you could do:
class User() {
void useClass( Base* p ) {
p->visit(visitor);
}
class Base() {
virtual void visit(Visitor) = 0;
}
class A : public Base {
void aFun();
virtual void visit(Visitor v) override {
v.visit(this);
}
}
class B : public Base {
void bFun();
virtual void visit(Visitor v) override {
v.visit(this);
}
}
class Visitor {
void visit(B* b) {
b->bFun();
}
void visit(A* a) {
a->aFun();
}
}
By having this double dispatch with the visit function, you ensure that you call the function depending on the real type.
I don't think there is a compile time solution to your issue because in useClass (as it is now), there is no way (at compile time) to know the real type of p. If you want to have a compile time solution you need to do more changes. For example making useClass a template or overloading it, which mean you can't call useClass with a Base* any more ...
The fact that A and B share a common base class is irrelevant since they have different interfaces that you are using.
I would make C a template and store a pointer to the derived class instead of the base class:
template<typename T>
class CT {
public:
CT() {
p = std::make_unique<T>();
}
std::unique_ptr<T> p;
User m_user;
void doStuffWithUser() {
user.useClass(p);
}
};
Then you can simply overload useClass() to accept either A or B:
class User {
public:
void useClass(A* p) {
p->aFun();
}
void useClass(B* p) {
p->bFun();
}
};
Now you just have one compile time switch:
#ifdef useA
using C = CT<A>;
#else
using C = CT<B>;
#endif
You can rename aFun and bFun to Fun and make it virtual(also add it in Base class) and in useClass, use Fun method, compiler will figure out which method to use.
This will eliminate first macro.
For the second maybe you should use rewrite it in some other way, so you wouldnt use macros at all. I don't think you can reproduce this behavior without macros.
Maybe you should have some flag that you give to constructor, 1 to create object A or 0 to create object B and get this flag from user at the runtime.
EDIT
So maybe you can create function Fun that in class A calls aFun and in class B calls bFun.
You can create a template for User class and specialize it for class A and class B:
template<typename T>
class User
{
void useClass( Base* p );
}
template<>
class User<A>
{
void useClass( Base* p ) {p->aFun();}
};
template<>
class User<B>
{
void useClass( Base* p ) {p->bFun();}
};
Now in class C:
template<typename T>
class C {
C() {
p = new T();
}
Base* p;
User<T> m_user;
void doStuffWithUser() {
m_user.useClass( p );
}
}
As a final note, just avoid using new operator. Try std::unique_ptr or std::shared_prt
PS. I have not tested this code
if you do not want to change any interface you can use single #ifdef
class Base {};
class A : public Base {
public:
void aFun(){}
};
class B : public Base {
public:
void bFun(){}
};
#ifdef useA
typedef A impl_type;
auto correct_func = &impl_type::aFun;
#else
typedef B impl_type;
auto correct_func = &impl_type::bFun;
#endif
class User {
public:
void useClass( Base* p ) {
auto pointer = (static_cast<impl_type*>(p));
(pointer->*correct_func)();
}
};
class C {
C() {
p = new impl_type();
}
Base* p;
User m_user;
void doStuffWithUser() {
m_user.useClass( p );
}
};
Probably you could name both functions with the same name in A and B and make it virtual, so useClass will call only needed function.
Like
class User() {
void useClass( Base* p ) {
p->fun();
}
};
class Base() {
virtual void fun() = 0;
};
class A : public Base {
void fun();
};
class B : public Base {
void fun();
};
Also you can use some kind of constexpr function (if you are using c++11 standard or newer) to determine what type p is.
Edit:
After seeing comment, i think that you're probably can left yours aFun(), bFun(), and just add some fun() func which will be derived and call type-specific function.
Also, it may be helpful to try and create some adapter classes with same interfaces(as in gof patterns).
Edit2: I mean that there could be some function like
constexpr Base* chooseType(int a){
if(a == 0){
return new A();
} else {
return new B();
}
}
/////
C() {
int case = 0;
p = chooseType(case);
}
And it will be called in compile-time, so as choice of class.
If you can't change the interface, want to get rid of #ifdefs, and have compile-time guarantee of types being used, without run-time checks - I would suggest using combination of templates, and overloaded functions.
First of all, I would change class C to be a template:
template<typename Type>
class C
{
static_assert(std::is_base_of<Base, Type>::value, "Template argument of C is not base of Base!");
public:
C () {p = new Type;}
~C() {delete p;}
void fun () {u.useClass (p);}
private:
Type* p;
User u;
};
And, then would change User class to switch between different possible implementations of Base with overloaded functions:
class User
{
public:
void useClass (A* p) {p->aFun();}
void useClass (B* p) {p->bFun();}
};
And, then you would create object of C as follows:
C<A> ca;
If you forgot to implement type-specific useClass, or tried to use wrong type in C (i.e. not inherited from Base), you would get compile-time errors.
In addition, if some of the child classes of Base, that you want to switch between, have non-default constructors, you may pass a functor (e.g. std::function<Type*()>) to a C constructor, and use that to create an object.
Such a constructor may look like:
C (std::function<Type* ()> function) {p = function();}
And usage of it would look like:
C<Z> cz ([&]{return new Z(someInt);});
I have a global function within a namespace and this function is a helper function that will create objects and return them. However the return type is of the parent class, but the actual object returned is a subclass of the parent. It is then up to the user to cast it returned "parent" object to the appropriate subclass. I thought this is what polymorphism was about but I am not able to cast the returned object to a subclass. For example:
class Parent {...};
class ChildOne : public Parent {...};
class ChildTwo : public Parent {...};
Parent my_function(int x) {
if(x) {
return ChildOne();
}
else {
return ChildTwo();
}
};
int main() {
// The statement below is giving me an error (no matching function call...)
ChildOne my_child = (ChildOne)my_function(1);
}
No, you cannot cast the object returned by my_function to a subclass of Parent.
Since:
Parent my_function(int x) {
returns the object by value, it always returns an object of class Parent, and never a subclass. This is due to slicing.
For a discussion, see What is object slicing?
It is not possible as it is written in NPE's answer,
Since you asked in comment what you could do instead, this is how you can achieve (more or less) what you want in C++11.
#include <iostream>
#include <memory>
using namespace std;
class Parent {
public:
virtual ~Parent() { }
};
class ChildOne : public Parent {
public:
void say_hello() { cout << "Hello from ChildOne!" << endl; }
};
class ChildTwo : public Parent { };
unique_ptr<Parent> my_function(int x) {
if(x) {
return unique_ptr<Parent>{ new ChildOne() };
}
else {
return unique_ptr<Parent>{ new ChildTwo() };
}
}
int main() {
auto parent = my_function(1);
if (ChildOne* my_child = dynamic_cast<ChildOne*>(parent.get())) {
my_child->say_hello();
}
}
However, I would revise my code in such a way that the downcast (cast from parent to child) is not need. There are certain situations where it is needed or unavoidable but most of the time it is a sign of design flaw.
If I have a pointer to an object that derives from an abstract base class (so I cannot create an new object of that class), and I wish to make a deep copy of said object, is there a more concise way of accomplishing that than to have the abstract base class create a new pure virtual copy function that every inheriting class has to implement?
No, but the copy method does not have to be painful:
class Derived : public Base
{
public:
Base *copy() const
{
return new Derived(*this);
}
};
(assuming you already have a copy constructor, which, if you need a deep copy, you'll have).
The suggested 'copy', more usually called 'clone' is the normal approach. An alternative would be a factory and dispatch using rtti to find the right handler to then call the copy constructor on the derived type.
struct Abc
{
virtual void who() const = 0;
};
struct A : Abc
{
virtual void who() const { std::cout << "A" << std::endl;}
};
template<class T>
Abc* clone(Abc* abc)
{
T* t = dynamic_cast<T*>(abc);
if (t == 0)
return 0;
return new T(*t);
}
struct B : Abc
{
virtual void who() const { std::cout << "B" << std::endl;}
};
typedef Abc* (*Cloner)(Abc*);
std::map<std::string, Cloner> clones;
void defineClones()
{
clones[ typeid (A).name() ] = &clone<A>;
clones[ typeid (B).name() ] = &clone<B>;
}
Abc* clone(Abc* abc)
{
Abc* ret = 0;
const char* typeName = typeid(*abc).name();
if (clones.find(typeName) != clones.end())
{
Cloner cloner = clones[typeName];
ret = (*cloner)(abc);
}
return ret;
}
void test ()
{
defineClones();
Abc* a = new A;
Abc* anotherA = clone(a);
anotherA->who();
Abc* b = new B;
Abc* anotherB = clone(b);
anotherB->who();
}
Whilst the above works, the sheer fact it uses rtti would be enough to persuade most to go the normal approach. However, it there was a reason preventing changes to the base class, it might be useful.
It this efficient? The marginal cost of adding a new type is truly a one-liner. The catch is that it will be easy to forget to add that line with each new class. Or you can see it as an upside that all the clone code lives in a single file and we don't have to change the supported hierarchy to handle it.
A while back someone in comp.lang.c++ asked how to automatically create a clone() function. Someone else provided an idea upon which I expanded. None of it is tested code and I've never actually tried it...but I think it works: http://groups.google.com/group/comp.lang.c++/browse_thread/thread/c01181365d327b2f/9c99f46a8a64242e?hl=en&ie=UTF-8&oe=utf-8&q=comp.lang.c%2B%2B+noah+roberts+clone&pli=1