2016-06-05 3 views
0

Прежде всего, я только немного научился Java. Прошло всего несколько дней с тех пор, как я начал дружить с C++, поэтому, пожалуйста, не ставьте этот вопрос таким базовым и, пожалуйста, не меняйте мой вопрос.C++: как заставить геттеры и сеттеры работать с пустым конструктором

Я сделал простой исходный код следующим образом:

#include <iostream> 

using namespace std; 

class Car { 
    public: 
     void setBrand(string name); 
     void setPrice(double price); 
     string getBrand(); 
     double getPrice(); 
     Car(); 
     Car(string name); 
     Car(string name, double price); 

    private: 
     string name; 
     double price; 
}; 

Car::Car() { 
} 

Car::Car(string name) { 
    name = name; 
} 

Car::Car(string name, double price) { 
    name = name; 
    price = price; 
} 

void Car::setBrand(string name) { 
    name = name; 
} 

void Car::setPrice(double price) { 
    price = price; 
} 

string Car::getBrand(void) { 
    return name; 
} 

double Car::getPrice(void) { 
    return price; 
} 

int main() { 
    Car car; 
    car.setBrand("Nissan"); 
    car.setPrice(30000); 
    cout << "Brand: " << car.getBrand() << endl; 
    cout << "Price: " << car.getPrice() << endl; 
    return 0; 
} 

Я хотел бы сделать код, который создает пустой экземпляр класса под названием Car, установите значение поля позже и распечатать их на консоли.

Код не вызывал ошибок во время компиляции, но результат, который я вижу, полностью отличался от ожидаемого. Он не показывал название бренда, и цена выглядела даже странно:

Brand: 
Price: 6.95322e-310 

Кто-нибудь поможет мне! Большое вам спасибо заранее.

+5

Я люблю выражение * Прошло всего несколько дней с тех пор, как я начал дружить с C++ * - Не волнуйтесь - через 6 месяцев вы будете заполняться для развода –

+0

Совет. Не дайте каждой организации в вашей программе одно и то же имя, и вы вряд ли будете смущать себя. –

+0

Одна из идей состоит в том, чтобы префиксные переменные-члены, т.е. «m_name» –

ответ

3

Проблема заключается в том, что вы переопределяете имена членов с параметрами функции. Вы можете использовать this->, чтобы сделать его явным или назвать его по-разному.

Например:

void Car::setBrand(string name) { 
    this->name = name; 
} 

Или:

void Car::setBrand(string new_name) { 
    name = new_name; 
} 
+0

Привет, большое спасибо за ответ. Теперь я приближаюсь к CPP World! :) – MarshallLee

3

В конструкторе и сеттеры, вы не делают никакого различия между локальным параметром и члена класса.

name = name; 

И функциональный параметр, и член класса называются name. В настоящее время компилятор присваивает значение параметра самому себе и вообще не влияет на член класса. Это связано с тем, что параметр функции находится в более непосредственной области.

Возможные решения:

  1. Укажите this, обращаясь к члену класса: this->name = name;.
  2. Переименуйте параметр функции: name = _name;.
  3. Для конструктора, списков использования инициализатора:

    Car::Car(string name, double price) 
    : name(name) 
    , price(price) 
    { } 
    
+0

@ Kerrek Спасибо. Любая идея, зачем ему нужны 8 пробелов? Я думал, что у меня уже есть тайная уценка. – Rotem

+1

Потому что вы в списке, так что это лишний уровень иерархии. Если вы хотите выйти из списка и иметь код на верхнем уровне, вы можете вставить что-то вроде «

» в промежутке (или только немного более обычного текста). –

+0

@KerrekSB Спасибо за это. – Rotem

3

Там слишком много плохой код, чтобы описать его в прозе, так что позвольте мне представить фиксированную реализацию, и я оставляю его вам заметить разницу:

#include <string> 

class Car 
{ 
private: 
    static constexpr double kNoPrice = -1.0; 
    static constexpr const char* kNoName = "[no name]"; 

public: 
    // Main constructor: constructs a car with the given name and price. 
    Car(std::string name, double price) 
    : name_(std::move(name)) 
    , price_(price) 
    {} 

    // Convenience constructors: 
    Car() : Car(kNoName, kNoPrice) {} 
    Car(std::string name) : Car(std::move(name), kNoPrice) {} 

    // Accessors: 
    const std::string& getBrand() const { return name_; } 
    void setBrand(std::string name) { name_ = std::move(name); } 

    double getPrice() const { return price_; } 
    void setPrice(double price) { price_ = price; } 

private: 
    std::string name; 
    double price; 
}; 

Некоторые случайные ноты, в частности, нет порядка:

  • Используйте правильные имена. Это std::string, а не string, mate или buddy. Никогда не злоупотребляйте пространством имен.
  • Включите заголовки для внешних имен, которые вам нужны.
  • Чтение неинициализированных значений - это неопределенное поведение, поэтому ни один из ваших конструкторов не должен оставлять поля неинициализированными (например, price_).
  • Дайте частным членам последовательные имена (например, foo_ в моем примере).
  • Аксессуары должны быть постоянными.
  • Конструкторы удобств должны делегировать одному конструктору рабочей лошади.
  • Выберите разумные значения по умолчанию для начальных значений полей по умолчанию и сделайте их доступными для обнаружения.
  • Используйте семантику перемещения, когда вы приобретаете данные динамически управляемых данных (строки, динамические контейнеры и т. Д.).
Смежные вопросы