Syntax and overloading copy constructor - c++

I am new to the topic of overloading copy constructors and I just wanted someone to look at my code for my class and see if I am overloading my copy constructor correctly. It is only using a single string as user input. Also, do I need the '&' or not?
class TODO {
private:
string entry;
public:
List* listArray = nullptr;
int itemCount = 0, currInvItem = 0;
int maxLength = 22;
TODO() { entry = ""; };
TODO(const string& ent) { setEntry(ent); }; // Is this correct?
void setEntry(string ent) { entry = ent; };
string getEntry() const { return entry; };
void greeting();
void programMenu();
void newArray();
void getList();
void incList();
void delTask();
string timeID();
string SystemDate();
friend istream& operator >>(istream& in, TODO& inv);
friend ostream& operator <<(ostream& out, TODO& inv);
void componentTest();
void setTask(string a);
string getTask();
bool validTask(string a);
bool notEmpty(string e);
};

That's correct, but it's just a constructor of TODO taking a const reference to a string. You can test it here.
Passing const string& ent (by const reference) is not a bad idea. Another option would be to pass string ent (by value), and move that string when initializing entry, i.e. : entry{ std::move(ent) }. As here.
The class TODO has a default copy constructor. Check the line at the Insight window here (you'll have to click Play first).:
// inline TODO(const TODO &) noexcept(false) = default;
The default copy constructor would just copy the members, including the List pointer, but not the List elements (shallow copy). Notice both instances of TODO would be pointing to the same List elements, and any operation on them would affect both instances.
Should you want to implement a custom copy constructor, the syntax would be (see here):
TODO(const TODO& other) {
std::cout << "custom copy_ctor\n";
*this = other;
// Copy listArray elements
...
}

Related

Sorting vector of custom type with std::sort not working as expected

This is my class:
class Animal
{
///
protected:
const std::string name_;
}
This is my copy assignment operator:
Animal& Animal::operator=(Animal const& a)
{
return *this;
}
And here my sort:
std::sort(std::begin(animalVec), std::end(animalVec), [](Animal a, Animal b)
{
return a.getName().size() < b.getName().size(); // for some reason it doesn't sort
}
);
With:
std::string Animal::getName() const
{
return name_;
}
The code compiles but the order of the Animal objects inside the vector is the same after the sort. Why is it not sorting?
Thanks!
Your copy assignment is wrong. It does not modifies its left-hand side operand. You should look toward this:
Animal& operator=(Animal const& a)
{
name_ = a.name_;
return *this;
}
Then note:
The generation of the implicitly-defined copy constructor is
deprecated if T has a user-defined destructor or user-defined copy
assignment operator. - cppreference.com
Accordingly, then you'd want to omit the const for the name_ member. When you provide setter and getter methods, there's no need nor use in constness of this data member.
// ...
protected:
std::string name_;
// ...

Why is destructor called in Friend function

Why is Destructor Called in this Friend function show() C++?
Also, how should the character pointer be initialized, it was set as 0...
The full code with main is here https://justpaste.it/5x7fy
#include<iostream>
using namespace std;
#include<string.h>
class String
{
public:
char *p;
int len;
String()
{
cout << "empty constructor" << endl;
len=0;
p=0;
}
// constructor
String(const char *s) {
len=strlen(s);
p=new char[len+1];
strcpy(p,s);
}
friend String operator+(const String&s, const String&t);
friend int operator<=(const String&s, const String&t);
friend void show(const String s);
~String() {delete p;}
};
void show(const String s)
{
cout<<s.p<<endl;
}
Edit, read up on copy constructor and added one as:
// copy constructor
String(const String &s)
{
len=s.len;
p=new char[len+1]; // s.p;//
strcpy(p,s.p);
}
The friend function parameter was passed by value before and the variable left the show function scope, therefore the destructor was called, now it is passed by reference.
friend void show(const String & s);
...
void show(String & s)
{
cout<<s.p<<endl;
}
Edit updated the initialization of the character pointer in the empty constructor.
String() {
p = new char[1]{'\0'};
len = 1;
};
[latest source]: https://www.mediafire.com/file/31gb64j7h77x5bn/class38working.cc/file
The destructor is called because s is passed by value. That is, when you call show(something), that something is copied into s, which is later destroyed when execution of show ends.
Your friend function show takes the String parameter per value, which means that whatever argument is passed to the function, a local copy is created and used inside the function. Of course, this local copy is destroyed - again when the show() function ends.
If you pass the string by reference (const string**&** s), you won't get an extra temp copy nor any destruction of that.

C++ initializing const

I need to be able to initialize a const member inside the constructor, which counts up every time I create a new object. I was shown in school how its suppose to work, but I'm getting errors all the time. It's something to do with the copy constructor.
Here's the code and the compiler errors:
class kunde {
public:
kunde(string name, int alter);
kunde(const kunde& orig);
~kunde();
int GetAlter() const;
string GetName() const;
const int GetKnr() const;
private:
string name;
int alter;
const int knr;
static int cnt;
static int MaxKnr;
};
int kunde::cnt = 0;
int kunde::MaxKnr = 1000;
kunde::kunde(string name, int alter):knr(MaxKnr++) {
this->name = name;
this->alter = alter;
}
kunde::kunde(const kunde& orig):knr(MaxKnr++){
this->name = orig.name;
this->alter = orig.alter;
}
kunde::~kunde() {
}
int kunde::GetAlter() const {
return alter;
}
string kunde::GetName() const {
return name;
}
const int kunde::GetKnr() const {
return knr;
}
main.cpp: In function 'int main(int, char**)':
main.cpp:35:15: error: use of deleted function 'kunde& kunde::operator=(const kunde&)'
v[0] = v[1];
^
In file included from main.cpp:17:0:
kunde.h:19:7: note: 'kunde& kunde::operator=(const kunde&)' is implicitly deleted because the default definition would be ill-formed:
class kunde {
^~~~~
kunde.h:19:7: error: non-static const member 'const int kunde::knr', can't use default assignment operator
knr is suppose to be an account number. each time you create an object it creates a new const account number which stays.
As stated in comments, since knr is const, the compiler cannot generate a default copy-assignment operator= for the class, which is exactly what the compiler is complaining about for the v[0] = v[1]; statement:
note: 'kunde& kunde::operator=(const kunde&)' is implicitly deleted because the default definition would be ill-formed
const members cannot be re-assigned once initialized, thus cannot be copied.
The elements in a vector must be CopyAssignable and CopyConstructible (at least until C++11), but your class does not have a viable copy-assignment operator=, so it is not CopyAssignable (and it is not MoveAssignable in C++11 either, since a viable move-assignment operator= can't be generated, either).
The solution is to implement a copy-assignment operator= (and optionally a move-assignment operator=) that ignores knr, eg:
class kunde {
public:
kunde(string name, int alter);
kunde(const kunde& orig);
kunde(kunde&& orig);
...
kunde& operator=(const kunde& rhs);
kunde& operator=(kunde&& rhs);
...
private:
string name;
int alter;
const int knr;
...
};
kunde::kunde(string name, int alter)
: knr(MaxKnr++), name(name), alter(alter)
{
}
kunde::kunde(const kunde& orig)
: knr(MaxKnr++), name(orig.name), alter(orig.alter)
{
}
kunde::kunde(kunde&& orig)
: knr(MaxKnr++), name(std::move(orig.name)), alter(orig.alter)
{
}
kunde& kunde::operator=(const kunde& rhs)
{
if (&rhs != this)
{
name = rhs.name;
alter = rhs.alter;
// CAN'T BE DONE, SO IGNORE IT
// knr = rhs.knr;
}
return *this;
}
kunde& kunde::operator=(kunde&& rhs)
{
name = std::move(rhs.name);
alter = rhs.alter;
// CAN'T BE DONE, SO IGNORE IT
// knr = rhs.knr;
return *this;
}

Overloading Assignment Operator for a Class with Structure and enum's

I was trying to overload assignment operator for this Class.
How to do this for class containing Structures and enumerators?
class Config
{
public:
Config() { SetDefaults(); }
Config(const std::string& path);
enum FeatureType
{
kFeatureTypeHaar,
kFeatureTypeRaw,
};
enum KernelType
{
kKernelTypeLinear,
kKernelTypeGaussian };
struct FeatureKernelPair
{
FeatureType feature;
KernelType kernel;
std::vector<double> params;
};
bool quietMode;
std::string sequenceBasePath
int frameHeight;
std::vector<FeatureKernelPair> features;
friend std::ostream& operator<< (std::ostream& out, const Config& conf);
private:
void SetDefaults();
static std::string FeatureName(FeatureType f);
static std::string KernelName(KernelType k);
};
This is what i had tried. This is the general way to do it,right..?
Config & operator=(Config const&c) {
if(this != &c){
quietMode = c.quietMode;
sequenceBasePath = c.sequenceBasePath;
frameHeight = c.frameHeight;
features = c.features;
}
return *this;
}
This is one way to do it (assuming that you've defined the operator as member).
The copy swap idom suggested by CoryKramer in the comments is certainly a better approach (as long as you both have a copy operator and define a swap function).
Nevertheless, in your specific case, the Config class contains only members which already have an copy-assignement operator. So you don't need to provide your own: the default one generated by your compiler will organise a member by member copy.

Need working syntax for vector in class in this c++ .h-file

I can´t get the code to be vieved here for some unknown reason so I post my code with JavaScript snippets. Can anybody help me straighten this code out? I really need it to work and I am stuck. How can I write it so it works? I did put my code into JavaScript snippets but it´s not working. It is C++ code and i need a vector in a class.
class Bank {
public:
Bank(int m_size): konton(m_size, 0) {}
unsigned int getSize() const { return konton.size(); }
Bank(const Bank& _konton,) : konton(_konton){}
Bank(const Bank &rhs) : konton(rhs.konton) {}
Bank operator=(const Bank &rhs)
{
if (&rhs == this)
{
return *this;
}
konton = rhs.konton;
return *this;
}
void SetInfo(const int _konton)
{
konton = _konton;
}
int Konton() const { return konton; }
private:
vector<Bank> konton;
};
#endif
I cleaned a bit your mess and changed a bit metods, hope you gonna understand. But first of all take a look at rule of three/five/zero, because this code is mostly about it. Down below I pointed out some important things. It's not perfect, but should be got place to start.
class Bank {
public:
//
// Default constructor
// You don't need to define size of vector
Bank(): konton() {}
// Copy constructor
Bank(const Bank& other)
: konton(vector<int> (other.konton)) {
}
// Copy assignment operator
Bank operator=(const Bank &rhs)
{
if (&rhs == this) return *this;
konton = rhs.konton;
return *this;
}
// You missing destructor ~Bank();
//
// Also you can add two more functions:
// - Move constructor Bank(const Bank&& other);
// - Move assignment operator Bank& operator=(Bank&& other);
// This just add new element at the end of konton
void addKonto(const int _konto)
{
konton.push_back(_konto);
}
// And this remove last
void removeKonto()
{
konton.pop_back();
}
// Getters
vector<int> getKonton() const { return konton; }
unsigned int getSize() const { return konton.size(); }
private:
// I guess you mean to store accounts numbers in the Bank class
// To make it simple I made it int but, it can by any other your specific data type
vector<int> konton;
};
PS. Consider using IDE with on-the-fly syntax checking.
Edit: Here you have some more about this.