The fragment below is from a VC++ 2008 Express Edition.
Say, I have a class with a member that is a struct. I am trying to define default values for the member variables of this class. Why this does not work?
struct Country{
unsigned chart id;
unsigned int initials;
std::string name;
};
class world{
private:
Country _country;
unsigned int _population;
public:
world(){};
world():
_country():
id('1'), initials(0), name("Spain") {};
_population(543000) {}
:
:
~world(){};
};
There are two ways to initialize the country member data. Like this ...
struct Country{
unsigned char id;
unsigned int initials;
std::string name;
};
class world{
private:
Country _country;
public:
world()
{
_country.id = '1';
_country.initials = 0;
_country.name = "Spain";
}
~world(){};
};
... or, like this ...
struct Country{
unsigned char _id;
unsigned int _initials;
std::string _name;
Country(
unsigned char id,
unsigned int initials,
const std::string& name
)
: _id(id)
, _initials(initials)
, _name(name)
{}
};
class world{
private:
Country _country;
public:
world()
: _country('1', 0, "Spain")
{
}
~world(){};
};
Note that in the second example I find it easier to initialize the Country instance because I defined a constructor as a member of the Country struct.
Or, perhaps you want to give the Country type a default constructor:
struct Country{
unsigned char _id;
unsigned int _initials;
std::string _name;
Country()
: _id('1')
, _initials(0)
, _name("Spain")
{}
};
class world{
private:
Country _country;
public:
world()
{
}
~world(){};
};
The structure is an aggregate type.
Since it has no constructor you cannot initialise it with normal brackets, you can however use curly braces as you would initialise an array.
Related
I have a base class called Animal:
class Animal {
protected:
std::string name;
int age;
int weight;
public:
Animal(const std::string& _name, int _age, int _weight):name(_name),age(_age),weight(_weight) {};
virtual void animal_cange(Animal*) = 0;
};
and from the Animal class derives two sublasses
class Dog : public Animal {
public:
Dog(const std::string& _name, int _age, int _weight) :Animal(_name, _age, _weight) {};
void animal_cange(Animal* poot) override {
this = new Cat(poot->name,poot->age,poot->weight);
}
};
and this
class Cat : public Animal {
public:
Cat(const std::string& _name, int _age, int _weight) :Animal(_name, _age, _weight) {};
void animal_cange(Animal* poot) override {
this = new Dog(name, age, weight);
}
};
I made a virtual funcion in the base class caled virtual void animal_cange(Animal*) = 0; which should change a Dog object to a Cat object if it is called with the object's already existing name, age and weight value and visa versa but it always gives me error like:
assignment to 'this' (anachronism)
a value of type "Cat *" cannot be assigned to an entity of type "Dog *"
protected member "Animal::name" (declared at line 12) is not accessible through a pointer or object
I also tried without animal_change being a virtual function like this:
class Animal {
protected:
std::string name;
int age;
int weight;
public:
Animal(const std::string& _name, int _age, int _weight):name(_name),age(_age),weight(_weight) {};
};
class Dog : public Animal {
public:
Dog(const std::string& _name, int _age, int _weight) :Animal(_name, _age, _weight) {};
void animal_cange() {
this = new Cat(this->name,this->age,this->weight);
}
};
class Cat : public Animal {
public:
Cat(const std::string& _name, int _age, int _weight) :Animal(_name, _age, _weight) {};
void animal_cange() {
*this = new Dog(name, age, weight);
}
};
And the erorrs i get:
this = new Cat(this->name,this->age,this->weight); : "assignment to 'this' (anachronism)" and the entity error
"no operator matches these operands operand types are: Cat = Dog *"
In general, you cannot assign an object to one of a different class - that's what static type system is about. To "change" the dynamic type of a polymorphic object the client code can create another one like this:
Animal* animal = new Dog{}; // actually you should use smart pointers
if (want_to_change) {
delete animal; // prevents a memory leak; smart pointers perform it automatically
animal = new Cat{};
}
If you would like actual animal type choice to happen during initialization, consider using a factory:
class Factory {
public:
// may be static if uses no state, than you can just write a free function
Animal* produce(/* some parameters */) const;
};
Animal* Factory::produce(/* some parameters */) const {
if (should_be_cat(/* depending on the parameters */)) {
return new Cat{};
} else {
return new Dog{};
}
}
I want provide a class with a member function that will initialize the all member of class separately.
e.g.
#include <iostream>
using namespace std;
int x = 10;
class my{
public:
my():init{}
int &i;
void init()
{
i = x;
}
};
int main()
{
my m;
return 0;
}
I know if I can use "class my : i(init())" will work, but I have some special purpose to intialize like above.
However in above example, I'm getting following error:
class ‘my’ does not have any field named ‘initMy’.
How to resolve this?
If you are trying to write a constructor for class my, then it must be named with the class name. The following will work assuming that initMy is the name of another class that you are trying to subclass.
class my : initMy
{
public:
int i;
my() {
i = 10;
}
};
You might try to pre-initialize all the fields, then calling the initializing function inside the constructor:
class my {
public:
int i;
void initMy() {
i = 10;
}
my() : i(0) { initMy(); };
};
You could also (in C++11) define a bizarre signature for a private constructor, and delegate a constructor to it
class my {
private:
void initMy () { i=10; };
enum privateen {privatev};
my(enum privateen) : i(0) { initMy(); };
public:
my() : my(privatev) {};
int i;
};
Actually, I believe that your initialization should be in a constructor, not in some other function.
Few things to clarify here.
Member initialization list is for initialize members (mostly same purpose of the constructor).In initialize list nothing to do with member functions. in this example age(newAge) is not a function. It is initializing age variable.
class Man{
private:
int age;
string name;
public:
Man(int newAge):age(newAge),name("Jhon"){}
};`
You can use constructor to initialize the members of the class.
class Man{
private:
int age;
string name;
public:
Man(int newAge)
{
age = newAge;
name = "Jhone";
}
};
Alternatively you can use a init method to do initialization, if you have some issue to use constructor.
class Man{
private:
int age;
string name;
public:
Man(){}
init(int newAge, string newName)
{
age = newAge;
name = newName;
}
};
If you need to set the value of only one member in a class, you have to use a setter method
class Man{
private:
int age;
string name;
public:
Man(){}
setAge(newAge)
{
age = newAge;
}
setName(newName)
{
name = newNAme
}
};
edit:
class Man{
private:
int age;
string name;
public:
Man(initAge, initName)
{
setValues(initAge, initName);
}
setValues(newAge, newName)
{
age = newAge;
name = newName;
}
};
int main()
{
Man goodMan(34,"Jhon");
goodMan.setValues(45,"Kevin");
}
I have a struct, player, which is as follows:
struct player {
string name;
int rating;
};
I'd like to modify it such that I declare the struct with two arguments:
player(string, int)
it assigns the struct's contents with those values.
you would use the constructor, like so:
struct player {
player(const string& pName, const int& pRating) :
name(pName), rating(pRating) {} // << initialize your members
// in the initialization list
string name;
int rating;
};
Aside from giving your type a constructor, because as-shown it is an aggregate type, you can simply use aggregate initialization:
player p = { "name", 42 };
Although (as has been pointed out), you can simply add a constructor:
struct player() {
string name;
int rating;
player(string Name, int Rating) {
name = Name; rating = Rating;
}
};
Is there some reason you don't want to make it a class?
class player() {
public:
string name;
int rating;
player(string Name, int Rating) {
name = Name; rating = Rating;
}
};
You are allowed to declare a constructor for your player struct:
struct player {
string name;
int rating;
player(string n, int r) :
name(n),
rating(r)
{
}
};
In C++ one of the few differences between classes and structs is that class members default to private, while struct members default to public.
#include <boost/scoped_ptr.hpp>
class classA
{
protected:
struct StructB
{
int iAge;
double dPrice;
};
boost::scoped_ptr<StructB> m_scpStructB;
public:
classA(int age, double price)
: m_scpStructB(new StructB)
{
m_scpStructB->iAge = age;
m_scpStructB->dPrice = price;
}
/* DO NOT COMPILE <= second block
classA(int age, double price)
: m_scpStructB(new StructB),
m_scpStructB->iAge(age),
m_scpStructB->dPrice(price)
{}
*/
};
Question1> I have found that I cannot use the second block of code to initialize structure members pointed by a smart pointer. Is it a general c++ rule that we just cannot do it.
Please discard this question if the answer to the first question is "You cannot do it".
Question2> As far as I know, the order of assignment on initialization list is based on the order of member variables definition. Assume that you can initialize the member variables through smart pointer. How can you guarantee the order so that the smart point is initialized always first?
If you don't need StructB to be an aggregate/POD type, then just give it a constructor too:
#include <boost/scoped_ptr.hpp>
class classA
{
protected:
struct StructB
{
StructB(int age, double price) : iAge(age), dPrice(price) { }
int iAge;
double dPrice;
};
boost::scoped_ptr<StructB> m_scpStructB;
public:
classA(int age, double price) : m_scpStructB(new StructB(age, price)) { }
};
Otherwise you can just use a factory function, so that it remains a POD type:
#include <boost/scoped_ptr.hpp>
class classA
{
protected:
struct StructB
{
int iAge;
double dPrice;
static StructB* make(int age, double price)
{
StructB* ret = new StructB;
ret->iAge = age;
ret->dPrice = price;
return ret;
}
};
boost::scoped_ptr<StructB> m_scpStructB;
public:
classA(int age, double price) : m_scpStructB(StructB::make(age, price)) { }
};
I'm trying to define an array of type Class, for my homework. The classB and classC is defined inside another classA, and I have to define the an Array which
is defined inside classC of type classB. Below is the code I'm writing.
//main.cpp
...
//cop.h
class cop
{
public:
....
class Person
{
private:
static char name;
static char age;
static char gender;
};
class Station
{
public:
Station();
~Station();
private:
Person personArray[20];
protected:
void visit();
};
//cop.cpp
char cop::Person::name;
char cop::Person::age;
char cop::Person::gender;
cop::Station::Station(){}
cop::Station::~Station(){}
Person cop::Station::personArray[20];
I get following ERROR;
'Person' does not name a type
First of all (as I'm pointing out later) the fields of Person should not be static. After that, remove the following lines:
char cop::Person::name;
char cop::Person::age;
char cop::Person::gender;
Person cop::Station::personArray[20];
Properly designed your code should read like the following:
// Person.h
class Person
{
public:
char name;
char age;
char gender;
};
// Station.h
class Station
{
public:
Station();
~Station();
private:
Person personArray[20];
protected:
void visit();
};
// Station.cpp
Station::Station()
{
for (int i = 0; i < 20; i++)
{
personArray[i].age = ...;
}
}
By the way: declaring all fields of the Person class static will definitely make sure that all persons in your array have the same name, age and gender...