0

我不知道应该如何在我的非默认构造函数中处理传递的对象指针。我做错了这个程序,因为我觉得我不知道自己在做什么。

我已经坚持了一天半,我只是不明白。我将发布我必须使用默认构造函数和非默认构造函数的大部分作业。我还将包括我正在使用的类图,以便您了解变量/类/方法的功能。

我应该如何处理非默认构造函数中传递的指针?我无法通过这里分配任何值,因为它会告诉我它无法访问。在这段代码中:

Book::Book(string title, Author *pAuthor, Publisher *pPublisher, double price)
    {
        setTitle(title);
        setPrice(price);
    }

知道如何使用这些指针吗?现在我可以使用默认构造函数正确传递所有内容,但我可能做错了,因为我正在使用其他对象。基本上我不应该有两条线,Author author;Publisher publisher;我现在不在乎。

请帮忙!

Book.cpp 文件

#include <iostream>
#include <sstream>
using namespace std;

#include "Book.h"
#include "Publisher.h"
#include "Author.h"

class Book
{
    public:
        Book();
        Book(string title, Author *pAuthor, Publisher *pPublisher, double price);
        ~Book();
        void setTitle(string title);
        void setAuthorName(string first, string last);
        void setPublisher(string name, string address, string city);
        void setPrice(double price);
        string convertDoubleToString(double number);
        string getBookInfo();

    private:
        string title;
        double price;
        Author *pAuthor;
        Publisher *pPublisher;

    Author author;
    Publisher publisher;
};

Book::Book()
{
}

Book::Book(string title, Author *pAuthor, Publisher *pPublisher, double price)
{
    setTitle(title);
    setPrice(price);
}

Book::~Book()
{
}

void Book::setTitle(string  title)
{
    this->title = title;
}

void Book::setAuthorName(string first, string last)
{
    author.setFirstName(first);
    author.setLastName(last);
}

void Book::setPublisher(string name, string address, string city)
{
    publisher.setName(name);
    publisher.setAddress(address);
    publisher.setCity(city);
}

void Book::setPrice(double price)
{
    this->price = price;
}

string Book::convertDoubleToString(double number)
{
    return static_cast<ostringstream*>( &(ostringstream() << number) ) -> str();
}

string Book::getBookInfo()
{
    return title + "\n" + author.getFullName() + "\n" + publisher.getPublisherInfo() + "\n" + "$" + convertDoubleToString(price);
}

Main.cpp 文件:

#include <iostream>
#include <string>
using namespace std;

#include "Book.h"

int main()
{
    system("cls");

    cout << "Book 1" << endl;

    Author *pAuthor = new Author("John", "Doe");
    Publisher *pPublisher = new Publisher("Wrox", "10475 Crosspoint Blvd.", "Indianapolis");
    Book *pBook = new Book("Memory Management", pAuthor, pPublisher, 39.99);

    cout << pBook->getBookInfo() << endl;

    cout << endl << "Book 2" << endl;

    Book book;

    book.setTitle("Advanced C++ Programming");
    book.setAuthorName("Linda", "Smith");
    book.setPublisher("Microsoft Press", "One Microsoft Way", "Redmond");
    book.setPrice(49.99);

    cout << book.getBookInfo() << endl << endl;

    system("pause");

    return 0;
};

作者.cpp 文件:

#include <iostream>
#include <string>
using namespace std;

class Author
{
    public:
        Author();
        Author(string first, string last);
        string getFullName();
        void setFirstName(string first);
        void setLastName(string last);

    private:
        string firstName;
        string lastName;
};

Author::Author()
{
}

Author::Author(string first, string last)
{
    setFirstName(first);
    setLastName(last);
}

string Author::getFullName()
{
    return firstName + " " + lastName;
}

void Author::setFirstName(string first)
{
    this->firstName = first;
}

void Author::setLastName(string last)
{
    this->lastName = last;
}

类图:

在此处输入图像描述

4

3 回答 3

1

您需要为指针成员分配足够的内存来保存通过指针传递的数据,然后将传递的指针指向的数据复制到成员指针变量中。

简而言之,您需要对传递的指针成员执行深层复制。这样您的指针成员就拥有他们指向的数据。

编辑:
虽然你发布的灵魂似乎有效,但它仍然存在问题:

Book::Book() 
{     
    pAuthor = new Author();     
    pPublisher = new Publisher(); 
} 

为类指针成员动态分配内存,它们确实需要自己的内存分配,因为您的类应该拥有并控制这些成员的生命周期。
您可能想看看Member Initializer Lists。但是,接受 4 个参数的类的参数化构造Book函数仍然不分配任何内存。它仍然执行传递给它的指针的浅拷贝

什么是浅拷贝?

浅拷贝只不过是简单地指向某个地址的指针。这意味着您的指针不仅仅控制指向的对象。如果指向同一对象的其他指针释放了该对象(通过调用 `delete 等),那么你是一个指向不再存在的东西的指针,也就是一个悬空指针

当你这样做时会发生这种情况:

Book::Book(string title, Author* pAuthor, Publisher* pPublisher, double price) 
{
    ....
    this->pPublisher = pPublisher;           
    this->pAuthor = pAuthor;     
    ....
}

您需要避免这种情况的是Deep Copy

什么是深拷贝?

深度复制意味着,将您的指针分配一个单独的内存,然后将另一个指针的内容复制到您自己对象的内存中(与浅拷贝不同)。这将指针指向的对象的生命周期与指针的生命周期分开它是创建的。

为此,您应该为指针成员分配单独的内存,然后为=类的重载运算符分配内存,Author并且Publisher应该复制各个类的每个成员。查看复制和交换习语,了解如何在 C++ 中正确实现这一点。

于 2012-09-04T05:04:51.620 回答
1

除非赋值要求您使用指针数据成员,否则最好的解决方案是简单地将它们完全删除,并修改相关的构造函数,您也可以通过使用初始化列表来改进:

class Book {

  ....
 public:
  Book(std::string title, const Author& author, const Publisher& publisher, double price);
 private:
  // use some convention for private data member names, here trailing _
  std::string title_;
  double price_;
  Author author_;
  Publisher publisher_;

};

Book::Book(string title, const Author& author, const Publisher& publisher, double price)
 : title_(title), price_(price), author_(author), publisher_(publisher) 
{

}

编辑:由于似乎需要使用指针,并且由于Book该类具有尝试修改Authorand的方法Publisher,因此您需要对输入指针指向的对象进行深层复制。这意味着动态分配一个对象,new并将指向它的指针分配给您的指针数据成员之一。例如,

class A { .... }; // class with copy constructor

A* a1; // pointer to an A, points to nothing.
a = new A(); // a1 now points to dynamically allocated A. You are in charge of deleting!
A* a2(new A); // pointer to an A, initialized to point to dynamically allocated A.

但是随后您负责deleting动态分配的对象,并且必须修改您的类以使副本构造和分配合理,即遵循三规则。希望您会看到在这种特殊情况下使用指针会导致比其价值更多的问题。

于 2012-09-04T06:03:13.050 回答
1

与我的同学交谈几分钟后,我发现我遗漏了几行重要的代码。

我想我的问题的问题是我不明白我应该怎么做。在教授和同学的一些提示之后,我知道我在默认和非默认构造函数中缺少几行代码。

在这里,我将展示我正在寻找的内容:

Main.cpp文件:

#include <iostream>
#include <string>
using namespace std;

#include "Book.h"

int main()
{
    system("cls");

    cout << "Book 1" << endl;

    Author *pAuthor = new Author("John", "Doe");
    Publisher *pPublisher = new Publisher("Wrox", "10475 Crosspoint Blvd.", "Indianapolis");
    Book *pBook = new Book("Memory Management", pAuthor, pPublisher, 39.99);

    cout << pBook->getBookInfo() << endl;

    cout << endl << "Book 2" << endl;

    Book *book = new Book();

    book->setTitle("Advanced C++ Programming");
    book->setAuthorName("Linda", "Smith");
    book->setPublisher("Microsoft Press", "One Microsoft Way", "Redmond");
    book->setPrice(49.99);

    cout << book->getBookInfo() << endl << endl;

    system("pause");

    return 0;
};

Book.cpp文件:

#include <iostream>
#include <sstream>
using namespace std;

#include "Book.h"

Book::Book()
{
    pAuthor = new Author();
    pPublisher = new Publisher();
}

Book::Book(string title, Author* pAuthor, Publisher* pPublisher, double price)
{
    this->title = title;
    this->price = price;

    this->pPublisher = pPublisher;
    this->pAuthor = pAuthor;
}

Book::~Book()
{
    delete pAuthor;
    delete pPublisher;
}

void Book::setTitle(string  title)
{
    this->title = title;
}

void Book::setAuthorName(string first, string last)
{
    pAuthor->setFirstName(first);
    pAuthor->setLastName(last);
}

void Book::setPublisher(string name, string address, string city)
{
    pPublisher->setName(name);
    pPublisher->setAddress(address);
    pPublisher->setCity(city);
}

void Book::setPrice(double price)
{
    this->price = price;
}

string Book::convertDoubleToString(double number)
{
    return static_cast<ostringstream*>( &(ostringstream() << number) ) -> str();
}

string Book::getBookInfo()
{
    return title + "\n" + pAuthor->getFullName() + "\n" + pPublisher->getPublisherInfo() + "\n" + "$" + convertDoubleToString(price);
}
于 2012-09-06T01:00:14.320 回答