gpt4 book ai didi

C++ 处理堆上的对象

转载 作者:搜寻专家 更新时间:2023-10-31 00:28:27 25 4
gpt4 key购买 nike

我目前正在学习 C++,来自 C#/Java 背景,使用 visual studio 2017。

我有一个关于在堆上创建对象并在以后正确引用它们的问题。到目前为止,我遇到了多个教程和做事的方法。一些人建议尽可能多地使用智能指针,其他人则发誓它 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 有一个类型为 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;
}

child 是一个人, child 知道 child 的 parent 是谁是有道理的。但是,我不确定如何处理这种“知识”。这是我用于子类的代码:

//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");
}

这是我得到的输出:

enter image description here

我想我的问题仍然存在,谁能给我一个例子,说明应该如何被认为是好的 C++?

@user4581301 如果你看一下更新后的 main,你的意思是我应该返回 std::unique_ptr而不是 * (raw pointer) ?在这种情况下,我的函数将如下所示:

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++ 吗?

最佳答案

我认为了解 C++ 最重要的事情之一是:特别是如果您有 Java/C# 背景:

对象默认是值类型,不是引用类型!

你的整个代码可以简单地写成:

int main()
{
//this work
Person person("John Doe", 22);
//this work
Child child("Johnny Doe", 2, person);
cout << "---end of main---" << endl;
return 0;
}

看看代码是如何变成空的?您不必担心分配、删除未使用的对象等问题,因为对象不是引用类型!

我个人的规则层次是:

  1. 尽可能使用对象作为值类型。通过引用传递它们以避免复制。确保为相关类实现了有效的移动构造函数。作为值类型的对象 + 引用应该是 C++ 编程的默认方式。
  2. 如果你不能使用引用,因为你想指定一个丢失的对象,请使用 C 指针。无论如何,将 C 指针限制在最低限度,永远不要让它们管理任何东西。 C 指针基本上是某物的“查看器”,它们可以查看“无”(或空)。总是想着是否可以用 C++ 引用替换 C 指针。如果你可以做到,做到。
  3. 如果出于某种原因确实需要动态内存分配,例如动态多态性,请使用std::unique_ptr。请记住,C++ 主要作为静态多态性在模板上工作,而不是 Java 风格的继承+覆盖技术。
  4. 很少使用std::shared_ptr,并且只有当您确定有很多所有者时才使用,例如在不同线程上引用的对象。 std::shared_ptr 应在极端情况下使用。总是复制共享指针。永远不要通过引用传递共享指针。

无论如何,newnew[]deletedelete[] 几乎都被弃用了。只有图书馆作者应该在非常极端的情况下使用它们。 std::make_ 应该是在堆上分配对象的唯一方法,还有诸如 std::vectorstd::list

关于C++ 处理堆上的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45196598/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com