Copy constructor error - c++

I need someone to show me what is wrong with this code. I don't know what's wrong with it. I know the code doesn't do anything meaningful and it can't be used. I created it only to know how copy constructors work.
class test
{
public:
int* value;
public:
int getvalue()
{return *value;};
test(int x){ value = new int(x);};
test(const test& a)
{
value=new int;
*value = a.getvalue();
};
};

You need to change the declaration of getvalue() to int getvalue() const, since you're trying to call getvalue() on a const reference in your copy constructor.

There is a stray ; after each method definition, so will not compile.
class test { public:
int* value;
public:
int getvalue()
{return *value;}
test(int x){ value= new int(x);}
test(const test& a)
{
value=new int;
*value = a.getvalue();
}
};
Also, I'd avoid 'test' as a class name; depending on your platform if might be a macro or some other in-scpe name. Use "MyTest" or somesuch.

It's been a long time since I last wrote C++, but here goes:
I'm not sure why you're declaring value to be an int pointer; did you mean to make it an int?
class test
{
private:
int value;
public:
test(int x)
{
value = new int(x);
}
int getValue()
{
return value;
}
test(const test & a)
{
value = a.getValue();
}
};

(Posted on behalf of the OP).
I tried making the getvalue() function const and it worked. The problem was that I passed the test class as a const reference and because I didn't declare the getvalue() function const the compiler thought the function was going to change something in that reference.

Related

Calling functions inside of const references

Hi I am trying to have a getter in my class that returns a "read-only" reference to a vector of objects. Each of those objects its own variables and functions, that I need to call. The way that I am trying to set this up is to have the getter in the main class return a const reference. However, I don't seem to be able to access the values of the objects held in the vector. Is there a better way to do this? Here is a smallest reproducible example. Thank you.
#include <vector>
class Obj
{
private:
int val;
public:
Obj() { val = 10; }
inline int getVal() { return val; }
};
class Foo
{
private:
std::vector<Obj> obsVec;
public:
Foo()
{
Obj a;
Obj b;
obsVec.push_back(a);
obsVec.push_back(b);
}
const std::vector<Obj>& getConstRef() const { return obsVec; }
};
int main()
{
Foo foo;
foo.getConstRef()[0].getVal(); // Here is where I get the error
return 0;
}
The error that I get is:
Error (active) E1086 the object has type qualifiers that are not compatible with the member function "Obj::getVal"
You need to declare getVal() as const:
inline int getVal() const { return val; }
instead of:
inline int getVal() { return val; }
foo.getConstRef()[0] returns const A &, but getVal is not marked const.
Also note that inline is useless here, since functions defined (rather than declared) in class body are implicitly inline.

Copy struct to array with const values

I'm trying to replace a struct value that has a const value in a non const array but it fails to compile with:
Object of type 'Foo' cannot be assigned because its copy assignment operator is implicitly deleted
Here is an example:
struct Foo {
const int id;
int value;
Foo(): id(-1), value(-1) {}
Foo(int id): id(id), value(0) {}
};
int main(int argc, const char * argv[]) {
Foo foos[10];
foos[0] = Foo(1234);
return 0;
}
I'm coming from a swift background where that is valid as it copies the struct value into the array.
I tried making what I thought was a copy assignment operator but with const members what I tried didn't work either.
This is what I was trying to do for the copy assignment operator:
Foo& operator= (Foo newVal) {
// what do I put here!?
return *this;
};
Doing a memcpy to the array works but seems like the wrong sledgehammer for the job.
Being new at c++ I'm unsure what the correct pattern is for this type of flow.
C++ treats const very strictly. Copying such a struct will be painful if possible at all (without UB). Perhaps what you are really looking for is "readonly" instead? In that case you can make fields private with public getters/setters:
struct Foo {
public:
Foo(): id(-1), value(-1) {}
Foo(int id): id(id), value(0) {}
int getId() const {
return id;
}
int getValue() const {
return value;
}
void setValue(int newValue) {
value = newValue;
}
private:
int id;
int value;
};
You can never change a const value after it's been initialized.
From the name id it sounds like move semantics is what you need. Instead of having two valid objects with the same id, you can make it possible to move the data between objects, but not to copy it.
Example:
#include <iostream>
#include <utility>
struct Foo {
Foo() : id(-1), value(-1) {} // default - "invalid" values
Foo(int id, int value) : id(id), value(value) {} // constructor
explicit Foo(int id) : Foo(id, 0) {} // converting ctor, delegating
Foo(const Foo&) = delete; // no copy construction
Foo(Foo&& rhs) : // move construction ok
id(std::exchange(rhs.id, -1)), // take id, give -1 back
value(std::exchange(rhs.value, -1)) // take value, give -1 back
{}
Foo& operator=(const Foo&) = delete; // no copy assignment
Foo& operator=(Foo&& rhs) { // move assignment ok
// give the "moved from" element our id and value and
// take id and value from the "moved from" element
std::swap(id, rhs.id);
std::swap(value, rhs.value);
return *this;
}
int Id() const { return id; } // only const access
int& Value() { return value; } // non-const access in non-const context
int Value() const { return value; } // const access in const context
private:
int id;
int value;
};
int main() {
Foo foos[2];
foos[0] = Foo(1234); // The temporary Foo will have (-1, -1) when it's destroyed
for(auto& f : foos)
std::cout << f.Id() << ' ' << f.Value() << '\n';
}
Output:
1234 0
-1 -1
In C++, an object can be initialized only once. Your constant member is initialized via the default constructor when you declare the array. Then, you attempt to change that value via assignment
foos[0] = Foo(1234);
This fails, and righly so. One thing you could do is to have a container of not Foos, but some sort of pointers to foo. Thus, you will have allocated the memory for the pointers but will create the actual objects only when you can. For example:
Foo* foos[10]; //here you have only the pointers
foos[0] = new Foo(1234); //OK, the object is inialized here
You may consider using smart pointers such as std::unique_ptr instead of raw pointers here.
Times, and C++ standards have changed!
You can now define your own copy-assignment operator for classes that contain const member objects without undefined behavior as of c++20.
This was undefined behavior prior to c++ and remains so for complete const objects but not non-const objects with const members.
https://stackoverflow.com/a/71848927/5282154

Return function type example in C++

Current get() member function in class MyClass is defined as below, the return type is const int&. My question is what would be the difference if I defined get() function as
int& get() const
or
int get() const
? And which way is recommended?
#include <iostream>
using namespace std;
class MyClass {
int x;
public:
MyClass(int val) : x(val) {}
const int& get() const {return x;}
};
void print (const MyClass& arg) {
cout << arg.get() << '\n';
}
int main() {
MyClass foo (10);
print(foo);
return 0;
}
There's really nothing wrong with this code; logically it accomplishes more or less the same thing after the compiler inlines the get() method.
There's quite a big difference in some degenerate callers though:
const int *iptr = &foo.get(); // returns the address of x in the class.
On the other hand had you declared as follows:
class MyClass {
int x;
public:
MyClass(int val) : x(val) {}
const int get() const {return x;}
};
const int *iptr = &foo.get(); // Error!
I don't see any good reason for int& here. If you don't have one, people will frown on this code. Normally if people are expected to keep pointers to things around you don't return them by reference. The only reason you would want to return a pointer to a member is so that somebody can auto-pickup changes to it; and I have never seen a good use for that though I can imagine why some such thing might exist.
As for selbie's comment about assigning to it; it's a const reference; assigning to it is a compile time error.

Track member variable value change

I want to track when a particular member variable changes value so I can print it out. Now, the obvious solution to do this is to add a tracking function in the member's Set method, like so :
class Foo
{
public:
Foo() {}
void SetBar(int value)
{
//Log that m_bar is going to be changed
m_bar = value;
}
private:
int m_bar; // the variable we want to track
};
The problem I'm facing is that I'm working on a huge project and some classes have a lot of methods that internally change member variables instead of calling their Setters.
m_bar = somevalue;
Instead of :
SetBar(somevalue);
So I'm wondering if there's a faster/more clean method to achieve what I want than just changing every m_bar = to SetBar(. An assignment operator overload only for that member variable perhaps?
If it is possible for you to change the data type of the member, you can change it to a logger type.
Example:
#include <iostream>
template <class T>
class Logger
{
T value;
public:
T& operator=(const T& other)
{
std::cout << "Setting new value\n";
value = other;
return value;
}
operator T() const
{
return value;
}
};
class Foo
{
public:
Foo() {}
void SetBar(int value)
{
//Log that m_bar is going to be changed
m_bar = value;
}
private:
#if 1
Logger<int> m_bar; // the variable we want to track
#else
int m_bar; // the variable we want to track
#endif
};
int main()
{
auto f = Foo();
f.SetBar(12);
}
Online example at ideone.

Are there any alternatives to making const version of class?

In C++ I'm often facing a situation when I need to prepare const and non-const version of class in analogy to const_iterator and iterator from standard library.
class const_MyClass
{
public:
const_MyClass(const int * arr):
m_arr(arr)
{
}
int method() const; //does something with m_arr without modifying it
private:
const int * m_arr;
}
class MyClass
{
public:
MyClass(int * arr):
m_arr(arr)
{
}
int method() const; //does something with m_arr without modifying it
void modify(int i); //modify m_arr
private:
int * m_arr;
}
The problem with this is that I need to repeat whole code of const_MyClass in MyClass and distribute any changes in API to both classes. Thus sometimes I inherit const_MyClass and do some const_casts, which also isn't perfect and pretty solution. Still when I want to pass const_MyClass instance by reference it looks moronic:
void func(const const_MyClass & param)
Instance param is marked with two "consts", and it has only const methods...
This is where const constructors would be handy, but are there any existing alternatives?
Some use examples to explain problem better:
//ok to modify data
void f(int * data)
{
MyClass my(data);
my.modify();
...
}
//cant modify data, cant use MyClass
void fc(const int * data)
{
const_MyClass my(data);
int i = my.method();
...
}
You can make a template class to act as a base, like this:
template<typename T>
class basic_MyClass
{
public:
basic_MyClass(T * arr) :m_arr(arr) {}
int method() const; //does something with m_arr without modifying it
private:
T * m_arr;
};
Then, for your const version, since it doesn't add anything, you can just use a typedef:
typedef basic_MyClass<const int> const_MyClass;
For your non-const version, you can inherit:
class MyClass : public basic_MyClass<int>
{
public:
using basic_MyClass::basic_MyClass; // inherit all the constructors
void modify(int i); //modify m_arr
};
Have you considered simply tracking two pointers and raising exceptions from the mutable operations when no mutable value is available? Maybe an example will help describe what I am thinking of.
class MyClass
{
public:
MyClass(int *mutable_data):
m_mutable_view(mutable_data), m_readonly_view(mutable_data)
{
}
MyClass(const int *immutable_data):
m_mutable_view(NULL), m_readonly_view(immutable_data)
{
}
int retrieve_value(int index) {
return m_readonly_view[index];
}
void set_value(int index, int value) {
require_mutable();
m_mutable_view[index] = value;
}
protected:
void require_mutable() {
throw std::runtime_error("immutable view not available");
}
private:
const int *m_readonly_view;
int *m_mutable_view;
};
The idea is pretty simple here - use a sentinel value to indicate whether modifications are possible or not instead of depending on the type system to do that for you. Personally, I would think about doing the inheritance based approach that #BenjaminLindley suggested but I wanted to present a slightly different solution that might not have occurred to you.
After talk with Neil Kirk I realized what I was doing wrong. I started by separating data from logic as he suggested.
This attempt resulted in two classes MyClassPtr and const_MyClassPtr. They only provide functions for data access (like iterators) and may look like that:
class const_MyClassPtr
{
public:
const_MyClassPtr(const int * arr);
int operator [](int i) const;
const int * ptr() const;
private:
const int * m_arr;
}
class MyClassPtr
{
public:
MyClassPtr(int * arr);
int operator [](int i) const;
int & operator [](int i);
const int * ptr() const;
int * ptr();
//promotion to const pointer
const_MyClassPtr () const {return const_MyClassPtr(m_arr);}
private:
int * m_arr;
}
Now it is clear that objects of these classes should be treated like pointers, so when I use them as function parameters I pass them by value!
void func(const_MyClassPtr param) //instead of void func(const const_MyClass & param)
To provide methods I have created MyClassOp class template and used static polymorphism.
template <class DERIVED>
class MyClassOp
{
public:
const DERIVED & derived() const {return static_cast<const DERIVED &>(*this)}
DERIVED & derived() {return static_cast<DERIVED &>(*this)}
int method() const; //operates on derived() const
void modify(int i); //operates on derived()
}
MyClassOp is a collection of methods. It does not have state. In general it is a trait. To make these methods accessible I overloaded -> and * operators
class const_MyClassPtr : private MyClassOp<const_MyClassPtr>
{
public:
const MyClassOp<MyClassPtr> * operator ->() const {return this;}
const MyClassOp<MyClassPtr> & operator *() const {return *this;}
...
}
class MyClassPtr : private MyClassOp<MyClassPtr>
{
public:
MyClassOp<MyClassPtr> * operator ->() {return this;}
MyClassOp<MyClassPtr> & operator *() {return *this;}
...
}
This works O.K., but is a bit cumbersome. If I have for example equality operator I need to write something like *myptr1 == myptr2 to compare values kept by two MyClassPtr objects (it's easy to make a mistake and compare myptr1 == myptr2 or expect that something like *myptr1 == *myptr2 could work). Also when I have allocating type:
class MyClass : public MyClassOp<MyClass>
{
MyClass(int x, int y, int z);
...
int m_arr[3];
}
I would want to be able to use temporaries as function arguments.
void f(const_MyClassPtr my);
//use temporary when calling f()
f(MyClass(1, 2, 3));
I can do this by providing conversion operators or conversion constructors (that convert MyClass to const_MyClassPtr). But then const_MyClassPtr behaves more like reference than pointer. If iterators are generalization of pointers then why one could not imitate reference? Therefore I divided MyClassOp into two parts (const and non const) and replaced -> and * operators implemented by const_MyClassPtr and MyClassPtr with public inheritance and changed their names to ressemble reference. I ended up with following structures.
MyClassOp : public const_MyClassOp
const_MyClassRef : public const_MyClassOp<const_MyClassRef>
MyClassRef : public MyClassOp<MyClassRef>
MyClass : public MyClassOp<MyClass>
However const_MyClassRef and MyClassRef are not perfect generalization of reference as it impossible to imitate some of C++ reference properties, so Ref suffix is there to denote reference-like structure.
Maybe you can find some hints in effective c++ item 4 "Avoid duplication in const and non-const Member function"
I may summarize like following ( it makes you avoid code duplication even if using somewhat ugly cast ):
struct my_class
{
my_class(int x):_x(x){};
const int& method(void) const;
int& method(void);
int _x;
};
const int& my_class::method(void) const //func for const instance
{
return _x;
}
int& my_class::method(void) //func for normal instance
{
return const_cast<int& >(static_cast<const my_class& >(*this).method()) ;
}
int main()
{
my_class a(1);
const my_class b(2);
a.method() = 5;
cout << a.method() << endl;
//b.method() = 4; //b is const, wont compile
cout << b.method() << endl;
return 0;
}