0

C++ の別のクラスから継承し、いくつかのメソッドをオーバーライドするプログラムを作成しています。これらのメソッドに 1 行だけ追加したかったので、基本クラスでメソッドを呼び出し、その下に 1 行追加してみました。次のエラーが発生しました。

"Unhandled exception at 0x00FA4456 in Ch.12.exe: 0xC0000005: Access violation reading location 0x67525A64."  

これは、Javaで「スーパー」に到達できる最も近いものでした(私が理解しているように)。

クラスの簡易版

using namespace std;

#include <iostream>
#include <string>
#include "dateType2.h"

class extDateType : public dateType
{
private:
    string monthString;
    void updateMonthString()
    {
        string months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
        monthString = months[getMonth()];
    }
public:
void printDateString()
{
    string months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
    cout << months[getMonth()];
    cout << " ";
    cout << getYear();
}
extDateType(int month, int day, int year)
{
    dateType(month, day, year);
    updateMonthString();
}
void addDays(int x)
{
    dateType::addDays(x);
    updateMonthString();
}
};

int main()
{
    extDateType x(2, 25, 1996);
    x.addDays(10);
    x.printDateString();
    system("pause");
    return 0;
}

基本クラスの簡易版

using namespace std;

#include <iostream>
#include <string>

class dateType
{
private:
    int dMonth;
    int dDay;
    int dYear;
    bool isLeapYear;
public:
    dateType(){}
    void addDays(int x)
    {
        int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

        dDay += x;
        for(int i = dMonth-1; dDay > days[i]; i++)
        {
            dDay -= days[i];
            dMonth++;
            if(dMonth == 13)
            {
                dMonth = 0;
                dYear++;
            }
            i = i % 11;
        }
    }
    dateType(int month, int day, int year)
    {
        isLeapYear = false;
        int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if(month > 0 && month <= 12)
        {
            if(month == 2)
            {
                    if(year % 4 == 0)
                {
                    isLeapYear = true;
                    if(day > 0 && day <= 29)
                    {
                        dMonth = month;
                        dDay = day;
                        dYear = year;
                    }
                    else
                    {
                        cout << "Error" << endl;
                        dMonth = 1;
                        dDay = 1;
                        dYear = 2000;
                    }
                }
                else
                {
                    isLeapYear = false;
                    if(day > 0 && day <= 28)
                    {
                        dMonth = month;
                        dDay = day;
                        dYear = year;
                    }
                    else
                    {
                        cout << "Error" << endl;
                        dMonth = 1;
                        dDay = 1;
                        dYear = 2000;
                    }
                }
            }
            else
            {
                if(day > 0 && day <= days[month-1])
                {
                    dMonth = month;
                    dDay = day;
                    dYear = year;
                }
                else
                {
                    cout << "Error" << endl;
                        dMonth = 1;
                    dDay = 1;
                    dYear = 2000;
                }    
            }
        }
        else
        {
                cout << "Error" << endl;
            dMonth = 1;
            dDay = 1;
            dYear = 2000;
        }
    }
};

Visual Studio 2012 を使用しています。だれかが問題の原因を突き止めるのを手伝ってくれれば、大歓迎です。

4

1 に答える 1

5
extDateType(int month, int day, int year)
{
    dateType(month, day, year);

これが問題の修正です。上記を以下に置き換えてください。

extDateType(int month, int day, int year)
:dateType(month, day, year)
{

前者は未使用の一時オブジェクトを作成し、その行が実行された後に破棄されますが、後者は基本クラスのコンストラクターを正しく呼び出します。dateType(){}これは、コンパイラ エラーの原因となる を削除した場合に、より明確になる可能性があります。

基本クラスのコンストラクターが正しく呼び出されないため、updateMonthStringが呼び出されると、この行には、月の大きな初期化されていないジャンク値へのインデックスとしてのmonthString = months[getMonth()];配列アクセスが含まれます。したがって、クラッシュ

後者の構文は初期化リストと呼ばれ、デフォルト (引数なし) コンストラクターを持たない基底クラスとメンバー オブジェクトを初期化する正しい方法です。

またaddDays、Java で期待するようには機能しません。Virtual Functionsと呼ばれる概念を読む必要があります。デフォルトでは、すべての (非静的) 関数はvirtualJavaにありますが、以下を実行して C++ で手動で仮想化する必要があります。

class dateType
{

    ...
    virtual void addDays(int x){
  //^^^^^^^
    ...

};
于 2013-01-08T02:51:51.180 に答える