上のオブジェクトを扱う私は現在のVisual Studioに2017年C++は、ヒープ
を使用して、C#/ Javaの背景から来て、C++を学んでいる私は、ヒープ上のオブジェクトを作成し、適切に道の下にそれらを参照に関しては疑問を持っています。これまでは、私は複数のチュートリアルや方法を見つけました。可能な限りスマートポインタを使用することをお勧めする人もいれば、the devils toolを誓う人もいます。このような
私の現在の主なルックス:
//Main
Person *makePerson()
{
string name;
int age;
cout << "Input name: ";
cin >> name;
cout << "Input age: ";
cin >> age;
return new Person(name, age);
}
Child *makeChild(Person &parent)
{
return new Child(*makePerson(), &parent);;
}
int main()
{
cout << "---Input parent data---" << endl;
Person *person = makePerson();
cout << "printing: " << *person << endl;
cout << "---Input child data---" << endl;
Child *child = makeChild(*person);
cout << "printing: " << *child << endl;
cout << "---end of main---" << endl;
delete person;
delete child;
return 0;
}
機能は、個人データの入力を処理し、新しいPersonオブジェクトへのポインタを返します。次に、親参照を取り、残りのデータをmakePersonに問い合わせることで、子オブジェクトの作成を処理する関数を持っています。
これは良いC++と考えることができますか?どうすればそれをより良くすることができますか?私はいくつかのコード例を本当に感謝します。
すでに提案されているように、生ポインタをshared_ptr<Person> person
(重い)またはunique_ptr<Person>
(より共有されたもの)に置き換えることができます。
これは、PersonクラスとChildクラスのコードです。 Childには、タイプPerson *parent
の生ポインタがあることに注意してください。
//header
class Person
{
protected:
std::string name;
int age;
public:
Person();
Person(const Person& other);
Person(std::string inName, int inAge);
~Person();
virtual void print() const;
std::string getName() const;
int getAge() const;
Person &operator=(const Person &other);
//overload print functionality, act as if it was toString
friend std::ostream &operator<<(std::ostream &out, const Person &p);
};
//cpp
Person::Person() : name(""), age(0) {
std::cout << "Person empty constructor" << std::endl;
}
Person::Person(std::string inName, int inAge) : name(inName), age(inAge) {
std::cout << "Person (" << name << ") default constructor" << std::endl;
}
Person::Person(const Person & other) : name(other.name), age(other.age) {
std::cout << "Person (" << name << ") copy constructor" << std::endl;
}
Person::~Person() {
std::cout << "Person (" << name << ") destructor" << std::endl;
}
void Person::print() const {
std::cout << name << ", " << age << std::endl;
}
std::string Person::getName() const
{
return name;
}
int Person::getAge() const
{
return age;
}
Person & Person::operator=(const Person & other) {
std::cout << "Person (" << other.name << ") assignment constructor" << std::endl;
name = other.name;
age = other.age;
return *this;
}
std::ostream &operator<<(std::ostream &out, const Person &p) {
return out << p.name << ", " << p.age;
}
子供は人であり、子供が誰の子供の親であるかを知ることは理にかなっています。しかし、この "知識"をどのように扱うかは不明です。ここで私は子クラスのために使用していたコードは次のとおりです、私は私の質問が残っていると仮定し
誰も私にそれが必要かの例を与えることができる:
//Header
class Child : public Person
{
private:
const Person *parent;
public:
Child();
Child(std::string name, int age);
Child(std::string name, int age, const Person *parent);
Child(const Child &child, const Person *parent);
Child(const Person &person);
~Child();
Child &operator=(const Child &other);
void print() const;
friend std::ostream &operator<<(std::ostream &out, const Child &c);
};
//cpp
Child::Child() {
std::cout << "Child empty constructor" << std::endl;
}
Child::Child(std::string name, int age) : Person(name, age), parent(nullptr) {
std::cout << "Orphan (" << name << ") constructor" << std::endl;
}
Child::Child(std::string name, int age, const Person *parent) :
Person(name, age), parent(parent) {
std::cout << "Child (" << name << ") default constructor" << std::endl;
}
Child::Child(const Child &child, const Person *parent) :
Person(child.name, child.age), parent(parent) {
std::cout << "Child (" << child.name << ") copy constructor" << std::endl;
}
Child::Child(const Person &person) : Person(person), parent(nullptr) {
std::cout << "Child from person (" << name << ") constructor" << std::endl;
}
Child::~Child() {
std::cout << "Child (" << name << ") destructor" << std::endl;
}
Child & Child::operator=(const Child & other) {
name = other.name;
age = other.age;
parent = other.parent;
std::cout << "Child (" << name << ") assignment constructor" << std::endl;
return *this;
}
void Child::print() const {
if(parent)
std::cout << *this << " is child of " << *parent << std::endl;
else
std::cout << *this << " is orphan" << std::endl;
}
std::ostream &operator<<(std::ostream &out, const Child &c) {
return out << c.name << ", " << c.age << " is " <<
(c.parent ? ("child of " + c.parent->getName() + ", " + std::to_string(c.parent->getAge())) : "orphan");
}
は、これは私が手に出力されC++と見なされるように見えますか?
@ user4581301あなたが更新されたメインを見れば、* (raw pointer)
の代わりにstd::unique_ptr
を返さなければならないのですか?その場合には、私の関数は次のようになりますよう
std::unique_ptr<Person> makePerson2()
{
string name;
int age;
cout << "Input name: ";
cin >> name;
cout << "Input age: ";
cin >> age;
return std::unique_ptr<Person>(new Person(name, age));
}
そして、変数宣言:
std::unique_ptr<Person> upParent = makePerson2();
cout << "printing: " << *upParent << endl;
することは、これは私がこれまで持っているものよりもC++「より良い」と考えることでしょうか?
はい、 'std :: shared_ptr'は重いですが、必要な時間はかなり短いです。ほとんどの場合、 'std :: unique_ptr'はあなたが本当に望むものであり、ほとんどの場合、それはゼロのオーバーヘッドです。 – NathanOliver
'string * s =新しい文字列(" Hello world ");'ほとんどの場合、std :: stringでこれをしたくありません。 – drescherjm
編集と 'makePerson2'について:はい。それは良いでしょうが、もしあなたがC++ 14コンパイラを持っていれば '' make_unique'(http://en.cppreference.com/w/cpp)として 'return std :: make_unique(name、age);/memory/unique_ptr/make_unique)は[いくつかの可能性のあるエラーの場合]を排除します(https://stackoverflow.com/questions/37514509/advantages-of-using-make-unique-over-new-operator) –
user4581301