I am working on a project which handles the Data of a Library Section having multiple classes. Interface of interest of a class here is this.
class Author
{
private:
//data members
public:
Author (string _name) ;
Author (string _name, int _books) ;
} ;
Data is present with at least the name of the author, and no. of books may come along. I cannot have a default constructor here naturally. But if create a static array like this.
Author auth_arr[100] ;
Compiler gives me error due to absence of default constructor. But this statement is invalid as well.
Author auth_arr[100] ("Jacob") ;
Is there any method by which i can create this array and call the constructor of my choice, instead of making another method?
You can do this to a very limited extent. The trick is to call those constructors explicitly inside curly braces inside separated by commas, and instantiate the static array this way.
Author auth_arr [3] = {Author(“Kevin”, 7) ,Author(“Martha”) ,Author(“Shuan”, 15) } ;
But this method is literally a nightmare. You can do this for a size 5 or 10 array but not for a 50 size array or any more than that. So the better option is to make another method and call it passing the details as its arguments. Remember this is only for static arrays as you asked. For dynamic arrays, which are more frequently used than static, even this method is not applicable.
C++ does not allow you another method to call constructors of your choice. So default constructor should be defined in the class to get called at instantiation. Then, an appropriate method could be called afterwards with the data.
Another better thing would be to use std :: vector. Its detail you can find in another similar question here.
Constructors and array of object in C++
Are you really sure default c-tor has no sense here?
I would suggest this solution:
class Author
{
private:
//data members
public:
static string default_name;
Author (string _name = default_name);
Author (string _name, int _books);
} ;
string Autor::default_name = "NOBODY";
If you really insist to have 100 Jacobs, then do it in this way:
Author::default_name = "Jacob";
Author auth_arr[100];
Author::default_name = "NONE";
[UPDATE1]
However this works for local arrays only.
With a little trick you can use it for static/global arrays. I am not going to present it - because there is another solution to make static array of class without default constructor which I understand from your comment is your goal ;) With little help of macros you can even generate thousands of objects:
#define MAKE_10(X) X,X,X,X,X,X,X,X,X,X
Author auth_arr[101] = {
MAKE_10(MAKE_10(Author("Jacob", 0))),
Author("Jacob", 0)
};
Related
This question is about writing good code in terms of readability/best practices.
Especially when working with a larger class and methods, I would prefer to be verbose when using attributes of the class. A simple example would be changing the value of an attribute through a method. In python, this would be done like "self.some_attribute", where the "self." makes it verbose and readable imo.
In C++, there is different ways of doing it.
Without the namespace:
class Example{
public:
int size = 10;
void setSize(int new_size){
size = new_size;
}
};
With the namespace:
class Example{
public:
int size = 10;
void setSize(int new_size){
Example::size = new_size;
}
};
Is there a standard way to do it that's considered the better practice? I prefer the second, more verbose way but it can look ugly if the class name is big. Is there a different approach to go about this?
Another example for why I prefer the more verbose way is that if an input to the function has the same name as an atrribute, it won't throw an error but the attribute will not be modified:
class Example{
public:
int size = 10;
void setSize(int size){
size = size;
}
};
In Python, self. is critical because Python is a dynamic language. Imagine that self. wouldn’t be required:
class A:
def f():
x = 42 # whoops, is that a local or a member variable?
del x # what is deleted here?
return x # totally OK if there was another x in scope?
(the same problem effectively kills with in JS). But there is no such problem in C++! Each variable name is resolved at the time the method is compiled, and can’t change meaning afterwards.
So basically, while you definitely can access members via this->, there is little point in doing that.¹ All real IDEs are capable of highlighting members differently (some even distinguish own and inherited members). But from dark IDEless times, we still have common conventions of prefixing members with m_ or suffixing them with _ or likewise, as pointed out in the comments. That almost doesn’t hurt (esp. in comparison to lpdwsmthHere).
¹ Unless you’re writing a curiously recurring template or likewise where you can’t refer to an inherited member by bare name, because before instantiation, it is unknown whether there is an inherited member with such name. Much like in Python, but still during compilation.
I am curious as to whether any clarification can be provided on the multitudes of constructor syntax's there are in C++. I have seen constructors declared inside of classes, and outside of classes. I have also seen variable initialization through more common methods such as x = y or this-> x = y, but also through initialization lists, like Point(int i = 0):x(i) {}.
My question is whether there are certain situations where it is more suitable to use one style of constructor over another, or whether to declare the constructor inside or outside the class. Is their some commonly followed syntax guideline for this?
I feel it is generally a good idea to have constructors' destructors and other methods' prototypes inside the class itself, if they belong to the same class. It is more efficient and more programmer friendly.
for eg:
I would do something like this:
class decl ....{
private:
members var.. methods' prototype..
public:
decl(); default cons prototype
decl(type para....); parameterized cons prototype;
~decl();
some methods' prototypes..
};
Then you can always go ahead and use them take an argument to assign the value to instant variable
such as this:
decl::decl(can user the same name or different ){
if using the same name
this -> sameName = sameName;
otherwise,
instant data variable name = assign the value,
}
Thanks in advance for the replies.
store() is a function of Backpack class which is holding an array of pointers (Item * items). The arguments sent to store() are correct (tested by printing them out with cout). displayInventory() still prints the previous Item object's members at the end of the function.
void store(string & name, float weight, int power, int slot)
{
items[slot] = new Weapon(name, weight, power); // Weapon is a derived class of Item
this->displayInventory();
}
Thanks.
EDIT: Researching vectors now.
First, here are a couple of things which might ease your life (and the life of those who will read your code). It would simplify your code. Hence it will make easier to understand and debug:
Use relevant names for your variables.
Example:
void store(string & name, float weight, int power, int slot)
{
items[slot] = new Weapon(name, weight, power);
numItems+=1;
this->getInventory();
}
Use relevant / consistent names for your methods.
Here, it's hard to understand what is the purpose of getInventory() because it starts with get, yet its return type isvoid. (Maybe you meant buildInventory()?)
You don't need to redefine in your derive class, what is already in the base class.
In particular you don't need to redefine name, weight and power (and their getters) in Weapon, since it's already defined in Item
If you don't define any constructor in a class, the compiler will provide a default one without arguments.
It means you can remove the line Container(){;}
Don't reinvent the wheel. You'd better use a std::vector rather than trying to handling yourself pointers and arrays.
I'm pretty sure this last advice can by itself fix your issue. In particular, if you use a vector<Item>, you won't need to manipulate pointers yourself anymore. It means no more new and no more delete.
This is probably a very basic question but I never got around to understanding it properly. When I declare member variables I usually do within a class
class Bloke
{
public:
Bloke(): age(24) {}
int age;
}
So, I usually declare after the semicolon the member variables with "membera(), memberb()" etc. Over time I got a bit lazy and started to also include declarations of the member variables directly in {}, that is
Bloke(){age=24;}
int age;
Or even outside the class in the constructor separately. Can someone please explain if this is wrong? Thanks.
No it is not wrong and up until c++11 it was the only way. Most people however would consider the first way to be easier and more idiomatic for c++11, it is called constructor delegation. In c++11 you can also do inline initialization for some types like this:
class Bloke
{
public:
Bloke():{}
int age = 24;
};
The value for age will be 24 unless you change it somewhere else for all initialized objects. IMO constructor delegation should be used for any situation where applicable and save the body of the constructor for extra work.
I have created a simple class that takes an argument to the constructor as shown below.
class Jam
{
int age;
std::string name;
Jam *jam;
Jam(std::string argName) {
name = argName;
}
};
It takes the argument and initializes the Jam's name to the parameter passed. The only problem is that I'd like to be able to pass another copy of Jam to the constructor so I can initialize its pointer to an existing class by copying the values. Normally in C++ you could specify Jam *jam = new Jam(existingJam); and it would be copied by default, but since I already have std::string argName as a parameter, it refuses to let me do this.
I read an article here that explains how to create your own copy constructor, but it is rather tedious and involves copying each class member individually which seems like it would not make much sense for a class with 10+ data members. Is there a better way to do this than initializing each member individually?
Jam::Jam(std::string argName, Jam *argJam)
{
age = argJam->age;
//etc...
}
[It's quite possible I don't understand what you're asking, but here goes...]
The compiler provides a copy constructor if you don't write one yourself. Its behaviour is to copy each member variable in turn.