如何正确初始化这些变量?

时间:2020-06-26 00:00:03

标签: c++ initialization

更新2:

它正在编译,但仍发出相同的警告。我很沮丧。

更新:

使用这些构造函数无效,并且仍然会产生相同的警告。据我了解,这就是变量的初始化方式。我的猜测是,我作为一个初学者会犯一个简单的错误。

Ship::Ship()
{
    m_type[0] = '\0';
    m_engCnt = 0;
    m_engines[0] = {};
}

Engine::Engine()
{
    m_size = 0;
    m_type[0] = '\0';
}

警告:

Variable 'sdds::Ship::m_engines' is uninitialized.  Always initialize a member variable (type.6)

Variable 'sdds::EngineShip::m_type' is uninitialized.  Always initialize a member variable (type.6)

Variable 'sdds::Engine::m_size' is uninitialized.  Always initialize a member variable (type.6)

Using uninitialized memory 'invalid' -> MAIN.CPP  Line 50
Using uninitialized memory 'invalid' -> MAIN.CPP  Line 77

Buffer overrun while writing to 'this->m_engines':  the writable size is '400' bytes, but '480' bytes might be written.  -> SHIP.CPP Line 91

当我尝试按照在示例中看到的方式初始化变量时,编译器仍会在Engine和Ship类上生成未初始化的成员变量的警告。我知道这会导致进一步的错误。

这是我尝试过的:

// Ship.cpp

Ship::Ship() {   m_type = '\0';   m_engCnt = 0;   m_engines = {}; }

// Engine.cpp

Engine::Engine() {   m_size = 0.0;   m_type = '\0'; }

我仍然收到未初始化的变量警告,并且我知道我分配的内存不正确,因为我的整个程序都无法通过某些成员变量验证。当它运行时,它还会在最后一直循环循环出现相同的错误消息。

由于我还是C ++的新手,所以我很难发现自己做错了什么,而且我确定自己做错的事情是显而易见的和愚蠢的。因此,如果您能指出我鼻子上的鼻子,以免我被粘住,我将不胜感激!

我的问题是:

  1. 如何正确初始化这些变量?
  2. 是否存在明显的内存地址/分配错误?

这是有问题的代码:

// Engine.h

#pragma once
#ifndef SDDS_ENGINE_H
#define SDDS_ENGINE_H

namespace sdds
{
    const int   TYPE_MAX_SIZE = 30;                 // Max length of the type attribute in Engine class.
    
    class Engine
    {
        private:
            double  m_size;                         // The size of an engine, as a floating point number in double precision.
            char    m_type[TYPE_MAX_SIZE + 1];      // The engine model type, as an array of chars of size TYPE_MAX_SIZE.

        public:
            Engine() = default;                     // Default constructor.
            ~Engine() = default;                    // Default destructor.
            Engine(const char* type, double size);  // Custom constructor that rx's as params: engine type, size.
            double get() const;                     // Query that returns the size of the engine.
            void display() const;                   // Query that prints to the screen the content of an object in the format [SIZE] - liters - [TYPE] <ENDL>
    };
}

#endif



---

// Engine.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <iomanip>
#include "Engine.h"

using namespace std;

namespace sdds
{
    Engine::Engine(const char* type, double size)
    {
        // Validate explicit params:
        if (size > 0 && type[0] != '\0')
        {
            // Assign params to engine:
            strcpy(m_type, type);
            m_size = size;
        }
    }
    
    double Engine::get() const
    {
        return m_size;          // Return size of engine m_size.
    }

    void Engine::display() const
    {
        // Detect if Engine members are valid:
        if (m_size > 0 && m_type[0] != '\0')
        {
            // If valid, display m_size at precision 2, m_type:
            cout << fixed << setprecision(2) << m_size << " liters - " << m_type << endl;
        }
    }
}


---

// Ship.h

#pragma once
#ifndef SDDS_SHIP_H
#define SDDS_SHIP_H
#include "Engine.h"

namespace sdds
{
    const double    MIN_STD_POWER = 90.111;     // The minimum power of a ship, acc'g to the regulation.
    const double    MAX_STD_POWER = 99.999;     // The maximum power of a ship acc'g to the regulation.
    const int       MAX_NUM_ENGINES = 10;       // The maximum number of engines a ship can have.

    class Ship
    {
        Engine  m_engines[MAX_NUM_ENGINES];     // Statically allocated array of engines, of size MAX_NUM_ENGINES.
        char    m_type[TYPE_MAX_SIZE + 1];      // Ship model type, statically allocated arry of charss of TYPE_MAX_SIZE.
        int     m_engCnt;                       // The number of engines that are actually installed on the ship.

    public:
        Ship() = default;
        // ~Ship() = default;
        Ship(const char* type, const Engine arr[], int size);
        operator bool() const;
        bool operator<(double power) const;
        double calculatePower() const;
        void display() const;
        Ship& operator+=(Engine engine);
        
    };
    bool operator<(double power, const Ship& theShip);
}

#endif


---

// Ship.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iomanip>
#include <cstring>
#include "Ship.h"

using namespace std;

namespace sdds
{
    //Ship::Ship()
    //{

    //}

    Ship::Ship(const char* type, const Engine engines[], int cnt)
    {
        // Validate params:
        if (type != nullptr && engines != nullptr && cnt > 0)
        {
            // If valid, store params in current instance:
            strcpy(m_type, type);           // Copy string from params to current instance of m_type.
            m_engCnt = cnt;                 // Current instance of m_engCnt is set to param cnt.
            
            // Iterate through current instance's m_engines[i] and assign engines[i].
            for (int i = 0; i < cnt; i++)
            {
                m_engines[i] = engines[i];
            }
        }
        else 
        {
            // If params are invalid, set to a default empty state.
            m_type[0] = '\0';               // Default state for m_type = '\0'.
            m_engCnt = 0;                   // Default state for m_engCnt = 0.
        }
    }

    double Ship::calculatePower() const
    {
        double total_power = 0;
        for (int i = 0; i < m_engCnt; i++)
        {
            total_power += m_engines[i].get() * 5;
        }
        return total_power;
    }

    void Ship::display() const
    {
        if (*this)
        {
            cout << "No available data" << endl;
        }
        else
        {
            cout << m_type << "-";
            cout.setf(ios::fixed);
            cout.precision(2);
            cout.width(6);
            cout << calculatePower() << endl;
            cout.unsetf(ios::fixed);
            cout.precision(6);
            for (int i = 0; i < m_engCnt; i++)
            {
                m_engines[i].display();
            }
        }
    }

    Ship::operator bool() const
    {
        // Explain in the reflection what happens if the keyword explicit is removed, and why is it necessary.
        bool valid = true;
        m_type[0] == '\0' && m_engCnt == 0 ? valid = false : valid = true;
        return valid;
    }

    Ship& Ship::operator+=(Engine engine)
    {
        // Make sure the number of engines is less than max allowed:
        if (m_engCnt < MAX_NUM_ENGINES)
        {
            if (m_type[0] == '\0')
            {
                cout << "The object is not valid! Engine cannot be added!" << endl;     // Output error message.
            }
        }
        else
        {
            m_engines[m_engCnt + 1] = engine;
        }
        return *this;
    }

    bool Ship::operator<(double power) const
    {
        bool result = false;
        calculatePower() < power ? result = true : result = false;
        return result;
    }

    bool operator<(double power, const Ship& ship)
    {
        bool result = false;
        ship.calculatePower() > power ? result = false : result = true;
        return result;

    }

}


---

// Main.cpp

#include <iostream>
#include "Ship.h"
#include "Ship.h"
#include "Engine.h"
#include "Engine.h"

using namespace std;
using namespace sdds;

void printHeader(const char* title)
{
    char oldFill = cout.fill('-');
    cout.width(40);
    cout << "" << endl;

    cout << "|> " << title << endl;

    cout.fill('-');
    cout.width(40);
    cout << "" << endl;
    cout.fill(oldFill);
}

int main()
{
    {
        printHeader("T1: Testing Constants");

        cout << "TYPE_MAX_SIZE: " << sdds::TYPE_MAX_SIZE << endl;
        cout << "MIN_STD_POWER: " << sdds::MIN_STD_POWER << endl;
        cout << "MAX_STD_POWER: " << sdds::MAX_STD_POWER << endl;
        cout << endl;
    }

    {
        printHeader("T2: Testing Default Constructor");

        Ship invalid;
        invalid.display();
        invalid += Engine("D2", 2.1);
        cout << endl;
    }

    Engine engines[] = {
        Engine("V8", 4.4),
        Engine("V8", 5.0),
        Engine("Inline", 4.1),
        Engine("D3", 7.0),
        Engine("D0", 2.0),
        Engine("D1", 3.2),
    };

    {
        printHeader("T3: Testing Custom Constructor");
        
        Ship titanic("cruiser", engines, 6);
        titanic.display();
        cout << endl;
    }

    {
        printHeader("T4: Testing Conversion to Bool Operator");
        Ship invalid;
        Ship titanic("liner", engines, 1);

        if (invalid)
            cout << "1. Test Failed! Object should be invalid.\n";
        else
            cout << "1. Test succeeded!\n";

        if (titanic)
            cout << "2. Test succeeded!\n";
        else
            cout << "3. Test Failed! Object should be valid.\n";
        
        cout << endl;
    }

    {
        printHeader("T5: Testing += and < Operators");

        Ship titanic("liner", engines, 3);

        char type[]{ "D0" };
        while (titanic < sdds::MIN_STD_POWER)
        {
            type[1]++;
            cout << "Ship not up to standard. Required power: "
                 << sdds::MIN_STD_POWER << endl;
            titanic += Engine(type, 2.1);
        }

        titanic.display();

        if (sdds::MAX_STD_POWER < titanic)
            cout << "Too much power." << endl;
        else
            cout << "Ship doesn't exceed power regulation of: "
                 << sdds::MAX_STD_POWER << endl;
    }

    return 0;
}

3 个答案:

答案 0 :(得分:1)

检查控制流。

    Engine::Engine(const char* type, double size)
    {
        // Validate explicit params:
        if (size > 0 && type[0] != '\0')
        {
            // Assign params to engine:
            strcpy(m_type, type);
            m_size = size;
        }
    }

在其他条件下会发生什么? m_type和m_size未初始化。为什么不能只设置m_type ='/ 0'和m_size = 0?

        Engine::Engine(const char* type, double size)
    {
        // Validate explicit params:
        if (size > 0 && type[0] != '\0')
        {
            // Assign params to engine:
            strcpy(m_type, type);
            m_size = size;
        }
        else
        {
            m_type = '/0';
            m_size = size;
        }
    }

您的所有其他警告也是如此。您需要确保所有构造都是针对每条路径进行的。

因此,在查看Ship类时,还要检查ctor的控制流。

此外,仅在Ship的ctor中设置m_engCnt。问题是您允许添加引擎(这也会增加此计数)。您需要考虑这一点。

Ship& Ship::operator+=(Engine engine)
{
    // Make sure the number of engines is less than max allowed:
    if (m_engCnt < MAX_NUM_ENGINES)
    {
        if (m_type[0] == '\0')
        {
            cout << "The object is not valid! Engine cannot be added!" << endl;     // Output error message.
        }
    }
    else
    {
        m_engines[m_engCnt + 1] = engine;
        m_engCnt++;
    }
    return *this;
}

答案 1 :(得分:1)

您没有初始化成员变量。您将在之后分配给他们,然后使用垃圾自动对其进行初始化。

有两种方法可以初始化类成员变量:

  1. C ++ 11默认成员初始化
  2. 成员初始化器列表

我都喜欢,因为这是默认成员初始化的目的。使用默认成员初始化,以便默认构造函数按预期方式工作并具有合理的值,而用户定义的构造函数只需覆盖直接用作参数的变量即可。

//Note: Both of these are redundant. Pick one.
#pragma once
#ifndef SDDS_ENGINE_H
#define SDDS_ENGINE_H

namespace sdds
{
    const int   TYPE_MAX_SIZE = 30;                 // Max length of the type attribute in Engine class.
    
    class Engine
    {
        private:
            double  m_size{0.0};                         // The size of an engine, as a floating point number in double precision.
            std::string    m_type{};      // The engine model type, as an array of chars of size TYPE_MAX_SIZE.

        public:
            Engine() = default;                     // Default constructor.
            ~Engine() = default;                    // Default destructor.
            Engine(const char* type, double size);  // Custom constructor that rx's as params: engine type, size.
            double get() const;                     // Query that returns the size of the engine.
            void display() const;                   // Query that prints to the screen the content of an object in the format [SIZE] - liters - [TYPE] <ENDL>
    };
}

#endif

    Engine::Engine(const char* type, double size)
    : m_size(size)
    , m_type(type ? type : "") //Don't pass a nullptr to std::string's C-string constructor.
    {}

答案 2 :(得分:-2)

问题是以下几行:

 Engine  m_engines[MAX_NUM_ENGINES];

但是您从未真正为引擎数组分配内存。所以问题在于,记住声明一个int数组时,您需要执行以下操作:

int* foo = new int[size of array];

在这种情况下,我将避免使用静态数组,因为您不知道要添加多少艘船。

还有另一个问题: 再次将m_engines初始化为一个数组,该数组将存储Engine对象,但是:

m_engines[0] = {};

您要使用字符串设置Engine对象类型的第一个元素?在我看来,这非常可疑。...