I have a "abstract" super class called RealAlgebraicNumber and two inherited classes called IntervalRepresentation and NumericRepresentation. Both IntervalRepresentation and NumericRepresentation have a copy constructor and they work fine.
I use shared_ptr like this:
typedef std::tr1::shared_ptr<RealAlgebraicNumber> RealAlgebraicNumberPtr;
At another part of the programm I want to use the copy constructor for the abstract super class RealAlgeraicNumber:
RealAlgebraicPoint RealAlgebraicPoint::conjoin (const RealAlgebraicNumber& N)
{
vector<RealAlgebraicNumberPtr> v (mNumbers.begin(), mNumbers.end());
v.push_back(RealAlgebraicNumberPtr(new RealAlgebraicNumber(N)));
return RealAlgebraicPoint(v);
}
I did not define a copy constructor for RealAlgebraicNumber at all. I have no idea what it should do. The compiler is fine with the code, but unfortuantly when I test conjoin like this:
vector<RealAlgebraicNumberPtr> v;
v.push_back(RealAlgebraicNumberPtr(new NumericRepresentation(2)));
RealAlgebraicPoint PPP (v);
PPP.print();
PPP = PPP.conjoin (NumericRepresentation(3));
PPP.print();
The output is:
( 2 )( 2 null )
And print was defined like this:
void RealAlgebraicNumberFactory::print (const RealAlgebraicNumberPtr& A)
{
IntervalRepresentationPtr irA = std::tr1::dynamic_pointer_cast<IntervalRepresentation> (A);
NumericRepresentationPtr nrA = std::tr1::dynamic_pointer_cast<NumericRepresentation> (A);
if (irA != 0)
cout << irA->Interval();
else if (nrA != 0)
cout << static_cast<numeric>(*nrA);
else
cout << "null";
}
I use a loop to call the static-print function and put the representation between the ( ).
I tryed it the way Cat Plus Plus propused: virtual method in RealAlgebraicNumber,
virtual std::tr1::shared_ptr<RealAlgebraicNumber> clone();
implementation in e.g. NumericRepresentation
RealAlgebraicNumberPtr NumericRepresentation::clone()
{
return RealAlgebraicNumberPtr(new NumericRepresentation(*this));
}
And then used it like this in conjoin:
RealAlgebraicPoint RealAlgebraicPoint::conjoin (const RealAlgebraicNumber& N)
{
vector<RealAlgebraicNumberPtr> v (mNumbers.begin(), mNumbers.end());
v.push_back(RealAlgebraicNumberPtr(N.clone()));
return RealAlgebraicPoint(v);
}
Now the compiler complains:
RealAlgebraicPoint.cpp: In member function 'GiNaC::RealAlgebraicPoint GiNaC::RealAlgebraicPoint::conjoin(const GiNaC::RealAlgebraicNumber&)':
RealAlgebraicPoint.cpp:66:48: error: passing 'const GiNaC::RealAlgebraicNumber' as 'this' argument of 'virtual std::tr1::shared_ptr<GiNaC::RealAlgebraicNumber> GiNaC::RealAlgebraicNumber::clone()' discards qualifiers
I dont get it! Whats wrong?
Edit: Oke its fine! It had something to do with const, and virtual.
Thank you!
Joachim
If you didn't define a copy ctor, compiler will generate a default one, doing memberwise copy. What you probably want is polymorphic clone, to preserve the type, and call a proper copy ctor. For that, add a new virtual member, e.g. virtual RealAlgebraicNumber* clone();, and override it in every subclass to do return new T(*this); — then your conjoin will look like this:
RealAlgebraicPoint RealAlgebraicPoint::conjoin (const RealAlgebraicNumber& N)
{
vector<RealAlgebraicNumberPtr> v(mNumbers.begin(), mNumbers.end());
v.push_back(RealAlgebraicNumberPtr(N.clone()));
return RealAlgebraicPoint(v);
}
Related
I'm trying to overload the -> operator to eventually execute something along the lines:
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle(); //this works wonderfully
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
//the next line doesn't compile, I would like to achieve something like this, but even
//sharedPtrWrapper.get()->Toggle();
//would be nice to achieve, is this possible?
sharedPtrWrapper->Toggle();
//this works:
sharedPtrWrapper->operator->()->Toggle();
Note: I have no control over MyInterface, cannot implement the pure virtual destructor.
Here is what I tried (the below code runs):
#import <memory>
#import <iostream>
struct MyInterface {
virtual bool Toggle() = 0;
};
class A : public MyInterface {
public:
bool Toggle() {
stateEnabled = !stateEnabled;
std::cout<<"current state " << stateEnabled << std::endl;
return true;
}
private:
bool stateEnabled = false;
};
template <typename T>
class Wrapper {
private:
T *unsafePointer = nullptr;
public:
Wrapper<T>()
{ }
T *operator->() const {
return unsafePointer;
}
T *getInner() {
return unsafePointer;
}
Wrapper<T>(T *stuff) {
unsafePointer = stuff;
}
~Wrapper<T>() {}
};
int main(int argc, const char * argv[]) {
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle();
Wrapper<MyInterface> wrapperS(myInstance);
wrapperS->Toggle();
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
sharedPtrWrapper->operator->()->Toggle();
sharedPtrWrapper.operator->()->operator->()->Toggle();
sharedPtrWrapper.get()->operator->()->Toggle();
(*sharedPtrWrapper).operator->()->Toggle();
return 0;
}
Output:
current state 1
current state 0
current state 1
current state 0
current state 1
current state 0
Program ended with exit code: 0
To reiterate:
This code doesn't compile:
sharedPtrWrapper->Toggle();
How to make it compile?
Edit : I'm using a wrapper because I have no control over the MyInterface, I get it from a library, also shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>(myInstance); doesn't compile, because of the missing pure virtual destructor from the above mentioned interface.
Edit2: Example library usage in pseudocode:
void firstcallbackFromLib(Framework *framework) {
MyInterface *myInstance = framework->getInstance();
{
Wrapper<MyInterface> wrapperS(myInstance);
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(wrapperS);
//assign sharedPtrWrapper and framework to static instances
}
}
void myFunction() {
sharedPtrWrapper->Toggle(); //this doesn't work, this is what i'm trying to achieve
sharedPtrWrapper->operator->()->Toggle(); //this ugly thing works
}
void lastUninitCallbackFromLibrary() {
MyInterface *p = sharedPtrWrapper.get()->getInner();
framework->releaseInterface(p);
//etc
}
The problem is, that shared_ptr behaves like a pointer and Wrapper does that as well. In summary, you have code that behaves like a pointer to a pointer. In short, you could call (*sharedPtrWrapper)->Toggle(); instead of the abomination sharedPtrWrapper->operator->()->Toggle();.
Careful though: It's unclear what all this is supposed to achieve, because the example code is just an abstraction of your actual code. So, maybe it would just be more elegant to put a forwarding Toggle() method into class Wrapper, but that's impossible to tell with the info provided here.
I am confused about the question. Why wrapper class that does nothing?
If you want to put a class inside shared pointer yet do something uncommon at destruction: like, calling dll's function that performs the destruction, do some preprocessing, perform file closure instead of delete, or do nothing at all if that's what you want. Then you can simply specify it at shared pointer instantiation:
https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr - see construction option 5.
You don't need your wrapper at all.
shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>();
wont work because MyInterface is an abstract class. But, just like you can do
MyInterface *myInstance = new A();
To have a MyInterface * that points to a concrete derived object, you can use
std::shared_ptr<MyInterface> sharedPtr = std::make_shared<A>();
To get a std::shared_ptr<MyInterface> that points to a concrete derived object. You can then use sharedPtr to access Toggle like
sharedPtr->Toggle();
You can see that working in this live example
sharedPtrWrapper->Toggle(); doesn't compile because of operator-> chaining rules explained well in this answer. In principle: if your object is NOT a pointer, operator-> is called recursively, if it is a pointer, member access is performed. Now std::shared_ptr has overloaded operator-> to access the raw Wrapper<MyInterface>* pointer kept inside and when it is applied on it, it tries to access Toggle, which does not exist.
For clarity note that this code also will not compile:
Wrapper<MyInterface>* wrapper = new Wrapper<MyInterface>(myInstance);
wrapper->Toggle();
You can do this however:
(*sharedPtrWrapper)->Toggle();
Use:
struct CleanupMyInterface {
SomeTypeFromLib* somePointerFromLib = nullptr;
void operator()( MyInterface* ptr ) const {
if (somePointerFromLib && ptr)
somePointerFromLib->releaseInterface(ptr);
}
};
std::shared_ptr<MyInterface> sharedPtr( CreateAnInstanceOfAFromLibrary(), CleanupMyInterface{somePointerFromLib} );
shared_ptr has type-erased destruction, there is no need for a virtual destructor.
I'm trying to learn the concept of operator overloading in c++ but I have got stuck on a problem that I'm trying to solve using the operator+ where in the my main-function I add to userdefiend classes together.
The class constructor takes a string pointer as a parameter.
My understanding of the operatoroverloading concept is that you declare a function in a class, using the keyword operatorX, and replace X with the operator that you will like to overload. Like if i would like to overload the '-' operator I should write like this operator-. But when I debug my code it results in an Stack overflow and the program stops.
The class looks as follows:
class Hello{
public:
Hello(string str):pstr(&str){
}
//The overloaded function below
Hello operator+(Hello& h1){
Hello temp(*this);//creates a copy of the current Hello-object
temp = temp + h1;//adds the new value to the temporary object
return temp;
}
private:
string* pstr;//pointer to string-object
}
I know that i get the stack overflow in the overloaded function.
In the main method i have the following code:
void main(){
Hello h1("Hello ");
h1 + Hello("World");
}
I'm not shore that i've coded this in the right way but the result should be Hello World in the return object if i'm not mistaken.
How can I solve this so that I dont get the stack overflow when the code is running, and also how can I get the right return value?
in
Hello operator+(Hello& h1){
Hello temp(*this);//creates a copy of the current Hello-object
temp = temp + h1;//adds the new value to the temporary object
return temp;
}
the operator+ recursively calls itself, you have to really implement the addition
probably you wanted :
Hello operator+(const Hello& h1) {
Hello temp(*pstr + *(h1.pstr))
return temp;
}
Out of that, why do you have pstr as a pointer to a std::string rather than to have just a std::string str; ?
It is much more practical to have for instance :
class Hello{
public:
Hello(string s) : str(s) { }
Hello operator+(const Hello& h1){
Hello temp(str + h1.str);
return temp;
}
private:
string str;
};
Note if you really want to have string* pstr; your constructor
Hello(string str):pstr(&str){}
is wrong because you save the address of the parameter, you need to change it to for instance :
Hello(string str) : pstr(new string(str)) {}
and having a pointer you need to add the destructor to delete the string, and the copy constructor, the operator= etc look at rule_of_three
In operator overloading, the key concept to think is how would the behavior be if the type you were defining was a primitive type. For example, what would adding a pointer to string with another pointer to string look like.
As mentioned above, your definition is recursively calling operator+.
Here is an example that might be useful: https://www.geeksforgeeks.org/operator-overloading-c/
I'm trying to do something that seems like it should be fairly common but I've been unable to find anyone discussing it. this post on stackoverflow is similar to what I'm trying to do, but not quite the same.
I have an abstract base class:
#ifndef _ABASECLASS_H_
#define _ABASECLASS_H_
using namespace std;
#include <iostream>
#define CALL_MBR_FUNC(object, ptr_to_mem_func) ((object).*(ptr_to_mem_func))
class aBaseClass
{
public:
typedef void (aBaseClass::*aBaseClass_mem_func)();
int A;
int B;
aBaseClass();
aBaseClass(int a, int b);
virtual void function1(aBaseClass_mem_func infunc) = 0;
virtual void function2() = 0;
};
#endif /* _ACLASS_H_ */
and I have a derived class:
#ifndef _ASUBCLASS_H_
#define _ASUBCLASS_H_
using namespace std;
#include <iostream>
#include "aBaseClass.h"
/* A simple class containing two ints and some functions to demonstrate passing via various methods. It is a subclass of aClass*/
class aSubClass: public aBaseClass
{
public:
aSubClass();
aSubClass(int a, int b);
void function1(aBaseClass_mem_func infunc);
void function2(void);
};
#endif /* _ASUBCLASS_H_ */
where function1 and function2 are:
void aSubClass::function1(aBaseClass_mem_func infunc)
{
CALL_MBR_FUNC(*this, infunc)();
}
void aSubClass::function2(void)
{
A = 42;
B = 66;
}
Finally, in the main() I try to call function1 targeted on an object of type aSubClass, passing a pointer to function2 in aSubClass:
int main (int argc, const char * argv[])
{
aSubClass eh(2,5);
// This doesn't work
aBaseClass_mem_func trythis = &aSubClass::function2;
// This also doesn't work
eh.function1(&aSubClass::function2);
return(0);
}
OK, we can automatically cast a pointer-to-derived type to a pointer-to-base type. I have now read that we can't pass a pointer-to-derived-member-function to a pointer-to-base-member-function. I think I understand why (the derived member function might make use of things that exist in the derived class but don't exist in the base class).
But I'm trying to build a library of two categories of classes (derived from two base classes). Call them baseclass1 and baseclass2. One of the member functions in any derived class from baseclass1 needs to be able to be handed a particular member function from any derived class from baseclass2. Is there some trick I can use to carry out the necessary cast? Do I have to use the explicit keyword and define the cast somehow?
You could shorten this example a lot:
struct B {
virtual void foo() = 0;
};
struct D : B {
void foo() override { }
};
int main() {
void (B::*ptr)() = &D::foo; // error: cannot initialize a variable of
// type 'void (B::*)()' with an rvalue of type
// 'void (D::*)()': different classes ('B' vs 'D')
}
The error message, at least on clang, is pretty clear. gcc just says cannot initialize. The issue is just that you cannot implicitly convert a pointer-to-derived-member to a pointer-to-base-member. But you can do it explicitly with static_cast:
void (B::*ptr)() =
static_cast<void (B::*)()>(&D::foo); // ok!
Side-note: please remove the CALL_MBR_FUNC macro from your code and never write such a thing ever again.
Why it doesn't work:
One way you can think of a member function is this:
struct Foo {
void go () { }
} ;
Could also be expressed as:
void go ( Foo* this ) { }
So, this:
typedef void(Foo::*MemberFunctionPtr)() ;
Is kind of like this:
typedef void(*MemberFunctionPtrForFoo)(Foo*) ;
However, if you have a subclass like this:
struct Bar : public Foo {
void go2 () { }
} ;
That function is also kind of like this:
void go2 ( Bar* this ) { }
So when you take the address of Bar::go2, you're getting basically a pointer to a function that looks like void go2 ( Bar* this ). Why is this a problem?
Well let's look at what this means...
If you had this function:
void function ( Foo * this ) ;
And you were to do this:
Bar * bar = new Bar () ;
function ( bar ) ;
This would work (as it should). C++ kindly made it possible for you then to be able to do things like this:
void(*functionPtr)(Bar*) = &Foo::go ;
However, lets say you instead had this function:
void function ( Bar * this ) ;
And you did this:
Foo * foo = new Foo() ;
function ( foo ) ;
This wouldn't work because foo isn't [necessarily] a Bar. You could static_cast that, which is your way of telling the compiler "no, really, I'm pretty sure I know what I'm doing" (as opposed to reinterpret_cast, which is your way of telling the compiler "you're stupid; I know what I'm doing.")
Therefore, it also won't let you cast the member functions.
Another answer said that static_cast can convert the member functions, but that's only because static_cast is allowed to do the reverse of implicit cast (except for cv-qualification). You can do it, but it has the same caveats.
Disclaimer: this is a fairly simplified version of the spec, but it gets the point across.
A better solution in most cases:
On to a [potentially] better solution [unless absolute performance is key]: boost::function (or, as of C++11 std::function). This is a "functor".
Your member function could instead be written:
class Foo {
void function ( boost::function<void()> function ) { }
} ;
The functor object can be constructed with anything that can be called with the specified prototype (in this case, something taking no arguments and returning void). You can pass the address of a C-function for instance.
Another thing you can do is "bind" functions (which basically grabs arguments and makes a function). There's boost::bind for this.
For example you could do this:
Foo foo ;
Bar bar ;
foo.function ( boost::bind(&Bar::go2,&bar) ) ;
The boost bind takes some function as the first argument. If the function is a member function, the next argument must either be an instance of a class that the specified method can be called on (in which case it's copied) or a pointer to a class the specified method can be called on (in which case it's referenced). This example would actually cause the foo instance to call the bar instance (instead of itself), but you could pass &foo instead.
You can even be more creative:
class Foo {
void function ( boost::function<void(int)> function ) {
function ( 1 ) ;
}
void go2 ( int a , int b ) {
cout << a << " " << b << endl ;
}
} ;
Foo foo ;
foo.function ( boost::bind(&Foo::go2,&foo,_1,2) ) ;
That bind grabs:
The member-function-pointer for Foo::go2
A reference (or, 'pointer') to that instance of foo
A placeholder for "the first argument of the resultant function," which'll become the first argument in the call to go2
The number 2, which'll become the second argument in the call to go2
This is what'll be printed to the console:
1 2
This is an extraordinarily powerful tool and will lead you into the fantastic world of functional programming while making your life easier along the way. (It'll also make people like #CortAmmon hate you.)
I have a class, and let's called it class myClass
class myClass{
// some math operations
myClass get_difference(myClass &b)
{
print_operation(*this, b);
do_something else
return...
}
myClass get_sum(myClass &b)
// pseudocode
void print_operation(const myClass *a, const myClass &b)
{
if function == get_sum
print a << "plus" << b;
if function == get_difference
print a << "minus" << b;
}
// overload cout as well
};
Suppose I called the following
myClass anObject(1,2);
myClass anotherObject(3,4);
anObject.get_sum(anotherObject);
anObject.get_difference(anotherObject);
get_sum / get_difference will call print_operation, but I want to be able to determine the caller so a different output format is used.
Naive approach: Use switch-case
Add a new parameter called "id". Give each function (the caller) an id, and use switch-case statements in print_operation.
However, is there an alternative? A more elegant solution?
Thanks.
Have you considered adding a virtual const std::string& getFormatted() const in the caller?
If the format will be a function of both arguments to your operator, you would have to create some kind of table of combinations to look up your format.
If the format is only a function of the length of the printing of each argument (much simpler), you could use virtual size_t getFormatLength() const.
Note: print_operation() doesn't know anything about the caller, except that it has a getFormatted() function, yet the caller gets to format itself based on the value of op.
This is OOP/polymorphism at work.
As Andrew Marshall answered in his comment above, part of OOP/encapsulation is, you should not know anything about the implementation of the caller.
Polymorphism, done right, should try to encapsulate the implementation details away from the caller.
class myClass
{
public:
virtual std::string getFormatted( const std::string& op ) const = 0;
};
class A : public myClass
{
public:
virtual std::string getFormatted( const std::string& op ) const
{
// switch on the value of op or the length of op, etc...
return std::string( "this, formatted according to class A specs and op" );
}
};
class B : public myClass
{
public:
virtual std::string getFormatted( const std::string& op ) const
{
// switch on the value of op or the length of op, etc...
return std::string( "this, formatted according to class B specs and op" );
}
};
void print_operation(const myClass &a, const myClass &b )
{
std::string op;
if ( function == get_sum ) {
op = "plus";
} else if ( function == get_difference ) {
op = "minus";
}
std::cout << a.getFormatted( op ) << op << b.getFormatted( op );
}
Cpp functions don't know who is the caller unless you hack the stack, which is, kind of, complicated. So, generally speaking, you have to pass the information(in function parameter, template parameter, data member..) to print_operation to tell it what operation to print.
So the answer is no more elegant solution.
I don't think the problem boils down to knowing who the caller is. It sounds like you really want to define different ways to format the data and there may be different desired formatters for different callers.
Taking a lesson from .NET, you might consider a design where you have a format string to define how to output the data such as in IFormattable.ToString. In that example, a format string is used to differentiate different output formats. In your case, you could define it with an integer, an enum, or whatever is appropriate.
I have a question about the following code:
let's say I have a class P that has a copy constructor and a regular constructor the receives one string value.
I have the following code:
P doSomething(){
P p("myValue");
return p;
}
int main(){
P m=doSomething();
return 1;
}
why isn't copy constructor invoked at the return p of the doSomething() function?
the call P m=doSomething() - does it suppose to call the copy constructor or the operator=?
in case it's operator =, what is the difference of this code and the following:
P new_val=("newVal");
p m=new_val;
(i know here the call is for copy constructor)
Thanks,
Mary
why isn't copy constructor invoked at the return p of the doSomething() function?
The standard allows this copy to be elided. Google for [N]RVO. On certain compilers this happens only when optimizing, on others it is part of the calling conventions and thus happens always.
the call P m=doSomething() - does it suppose to call the copy constructor or the operator=?
T t = x; is "syntactic sugar" (in the sense that the T(x) is happening implicitly) for T t(T(x)) and thus has -- despite the = -- nothing to do with operator=. Note that also here the additional temporary may be elided, thus no copy ctor is called.
in case it's operator =, what is the difference of this code and the following:
This code makes no sense, what did you really mean?
P new=("newVal");
p m=new;
I made a small sample for demonstration.
void print(char* text, int ident)
{
for(int i = 0 ; i < ident ; i++)
{
printf(" ");
} // end for
fprintf(stdout, text);
fprintf(stdout, "\n");
fflush(stdout);
}
class P
{
public:
char* _str;
P (P& arg)
{
print("copy constructor", 2);
arg._str = this->_str;
}
P (char* str)
{
print("constructor", 2);
_str = str;
}
};
P doSomething(){
print("do something - function", 1);
P p("myValue");
print("before return p", 1);
return p;
}
int main(int argc, char* argv[])
{
print("start", 0);
P m=doSomething();
print("stop - call return", 0);
return 1;
}
this returns
start
do something - function
constructor
before return p
copy constructor
stop - call return
so copy constructor WILL BE CALLED
1) why isn't copy constructor invoked at the "return p" of the doSomething() function?
it should - try printing something to the console in the copy c-tor to see if it is really running.
2) the call P m=doSomething() - does it suppose to call the copy constructor or the operator=?
should call the operator=. again, use the debug message print from within the method to check
3) in case it's operator =, what is the difference of this code and the following:
P new=("newVal"); p m=new; (i know here the call is for copy constructor)
did you miss something on the code snippet? i think it won't compile