私のクラスの1つに問題があります。クラスには、array<>メンバーが1つだけ含まれています。このクラスの静的オブジェクトを作成し、関数の値を初期化しています。問題は、値が挿入されないことです。
デバッガーにステップインして、この配列へのいくつかの基本的な挿入ステートメントを見ると、配列は空のままです。ただし、挿入関数自体にステップインすると、まったく同じ名前の「2番目の」配列が表示され、期待どおりに値が格納されます。
私には、何も含まれていない静的な外部スコープの配列と、内容が適切に格納されている2番目の内部バージョン(まったく同じ配列)があるように見えます。
ここに欠けているものはありますか?なぜこれが起こっているのか私は本当に知りません。
リクエストに応じて、最小のソースコードは次のとおりです
Circularbuffer.hpp
#ifndef __ma__circularbuffer_guard
#define __ma__circularbuffer_guard
#include <array>
template < typename T, int SIZE>
class CircularBuffer
{
private:
int _index;
int _size;
std::array<T, SIZE> _buffer;
public:
CircularBuffer() { _index = 0; _size = SIZE; }
int length ();
typename T& at (int);
void insert (T);
int index ();
private:
int realign (int&);
};
template < typename T, int SIZE>
int CircularBuffer<T, SIZE>::realign (int& index)
{
if (index >= _size)
{
index -= _size;
realign(index);
} else if (index < 0)
{
index += _size;
realign(index);
}
return index;
}
template < typename T, int SIZE>
int CircularBuffer<T, SIZE>::length ()
{
return _size;
}
template < typename T, int SIZE>
typename T& CircularBuffer<T, SIZE>::at (int index)
{
realign(index);
return _buffer.at(index);
}
template <typename T, int SIZE>
void CircularBuffer<T, SIZE>::insert (T data)
{
realign(_index);
_buffer.at(_index) = data;
_index += 1;
}
template <typename T, int SIZE>
int CircularBuffer<T, SIZE>::index ()
{
return _index;
}
#endif
グローバルバッファ初期化子
#ifndef __guard__namespace__notes__
#define __guard__namespace__notes__
#include "circularbuffer.hpp"
#include <memory>
typedef CircularBuffer<char, 7> CB_Natural_T;
typedef CircularBuffer<int, 12> CB_Chromatic_T;
static CB_Natural_T WHITENOTES = CB_Natural_T(); // buffer of letter notes
static CB_Chromatic_T POSITIONS = CB_Chromatic_T(); // buffer of absolute positions on keyboard
struct Initialize
{
Initialize()
{
WHITENOTES.insert('C');
WHITENOTES.insert('D');
WHITENOTES.insert('E');
WHITENOTES.insert('F');
WHITENOTES.insert('G');
WHITENOTES.insert('A');
WHITENOTES.insert('B');
// Initialize all positions
for (int i = 0; i < 12; ++i)
POSITIONS.insert(i);
}
};
static Initialize dummy_init_var = Initialize();
#endif
静的バッファを初期化して、他のクラスの単体テストを実行できるようにします。
クラスヘッダーとcppに注意してください
#ifndef __guard__note__
#define __guard__note__
#include "macros.h"
#include <string>
#include <memory>
class Note
{
public:
enum Qualities { UNKNOWN = -3, DFLAT, FLAT, NATURAL, SHARP, DSHARP }; // qualities of note
typedef DEF_PTR(Note); // pointer type
private:
char _letter [1]; // the letter of the note
std::string _name; // the full name of the note
int _value; // absolute value
int _position; // relative position
Qualities _quality; // sharp/natural/flat quality
public:
Note();
Note(char); // letter
Note(char, Qualities); // letter, and quality
// setters
void sharp(); // Sets the quality of the note to 1
void Dsharp(); // Sets the quality of the note to 2
void flat(); // Sets the quality of the note to -1
void Dflat(); // Sets the quality of the note to -2
void natural(); // Sets the quality of the note to 0
// getters
char letter() const; /* returns character letter */
std::string name() const; /* returns true name of note */
int position() const; /* returns relative position on keyboard */
int quality() const; /* returns the quality of the note */
void respell() const; /* respells a note to the nearest other note */
static pointer_type make(char); // returns a shared pointer of a new Note
static pointer_type make(char, Qualities); // returns a shared pointer of a new Note
// operators
bool operator ==(Note& r) const; // Returns true if Notes are truly equal
bool operator !=(Note& r) const; // Returns true if Notes are truly not equal
bool isEnharmonic(Note& r) const; // Returns true if Notes are enharmonically equal
bool isNatural() const; // Returns true if Note is natural
bool isSharp() const; // Returns true if Note is sharp
bool isDSharp() const; // Returns true if Note is double sharp
bool isFlat() const; // Returns true if Note is flat
bool isDFlat() const; // Returns true if Note is double flat
private:
void makeName(); /* sets name of Note */
};
#endif
#include "note.h"
Note::Note()
{
_letter[1] = 'u';
_name = "";
_value = -1;
_quality = UNKNOWN;
_position = -1;
}
Note::Note(char l)
{
_letter[1] = l;
// determine absolute value based on letter
switch (l)
{
case 'C':
_value = 0; break;
case 'D':
_value = 2; break;
case 'E':
_value = 4; break;
case 'F':
_value = 5; break;
case 'G':
_value = 7; break;
case 'A':
_value = 9; break;
case 'B':
_value = 11; break;
default:
_value = -1; break;
}
_quality = NATURAL;
_position = _value + _quality;
makeName();
}
Note::Note(char l, Note::Qualities q)
{
_letter[1] = l;
// determine absolute value based on letter given
switch (l)
{
case 'C':
_value = 0; break;
case 'D':
_value = 2; break;
case 'E':
_value = 4; break;
case 'F':
_value = 5; break;
case 'G':
_value = 7; break;
case 'A':
_value = 9; break;
case 'B':
_value = 11; break;
default:
_value = -1; break;
}
_quality = q; // assert for good data
_position = _value + _quality;
makeName();
}
void Note::sharp() { _quality = SHARP; _position = _value + 1; makeName();}
void Note::Dsharp() { _quality = DSHARP; _position = _value + 2; makeName();}
void Note::flat() { _quality = FLAT; _position = _value - 1; makeName();}
void Note::Dflat() { _quality = DFLAT; _position = _value - 2; makeName();}
void Note::natural() { _quality = NATURAL; _position = _value; makeName(); }
char Note::letter() const { return _letter[1]; }
std::string Note::name() const { return _name; }
int Note::position() const { return _position; }
int Note::quality () const { return _quality; }
Note::pointer_type Note::make(char l) { return pointer_type(new Note(l)); }
Note::pointer_type Note::make(char l, Note::Qualities q) { return pointer_type(new Note(l, q)); }
void Note::makeName()
{
_name = "";
_name += _letter[1]; // add letter to name
// find out quality, add quality to name
switch (_quality)
{
case DFLAT:
_name += "bb"; break;
case FLAT:
_name += "b"; break;
case SHARP:
_name += "#"; break;
case DSHARP:
_name += "x"; break;
case NATURAL:
break;
default:
_name += "u"; break;
}
}
bool Note::operator ==(Note& r) const
{
// true if letter, value, position, and quality are all equal
return (_letter[1] == r._letter[1]) && (_value == r._value) && (_position == r._position) && (_quality == r._quality);
}
bool Note::operator !=(Note& r) const
{
return !(*this == r);
}
bool Note::isEnharmonic (Note& r) const
{
return (_position == r._position);
}
bool Note::isNatural() const
{
return _quality == NATURAL;
}
bool Note::isSharp() const
{
return _quality == SHARP;
}
bool Note::isDSharp() const
{
return _quality == DSHARP;
}
bool Note::isFlat() const
{
return _quality == FLAT;
}
bool Note::isDFlat() const
{
return _quality == DFLAT;
}
インターバルも投稿しますが、それはとても大きいです。しかし、基本的には、findIntervalと呼ばれるIntervals関数の1つにこのコードがあります
Interval :: findInterval
void Interval::findInterval(Note& bottom, Note& top)
{
int index = 0; // temp placeholder for start position
// find where the bottom note is in relation to buffer
for (int i = 0; i < WHITENOTES.length(); ++i)
{
if (bottom.letter() == WHITENOTES.at(i))
{
index = i; // set start position to this position
break;
}
}
// find the interpreted interval
// starting from index, with offset of length + index
for (int i = index; i < (index + WHITENOTES.length()); ++i)
{
if (top.letter() == WHITENOTES.at(i))
{
_interval = i - index; // set interval
break;
}
}
// modify index to serve as the position of the bottom note
index = bottom.position();
// find the physical distance
for (int i = index; i < (index + POSITIONS.length()); ++i)
{
if (top.position() == POSITIONS.at(i)) // values match
{
_distance = i - index; // set physical distance
break;
}
else if (top.position() > 11 && ((top.position() - 11) == POSITIONS.at(i))) // if top position is higher than octave
{
_distance = (i - index) + 11;
break;
}
}
}
静的構造体で初期化するために呼び出したにもかかわらず、WHITENOTESが空であるため、ここでデータメンバーを設定できません。
もう1つ注意すべき点は、ut_intervalをコンパイルすると、すべてのテストが失敗することなく完全に戻り、デバッガーでバッファーの値を確認すると、\0として表示されることです。ただし、それでもifステートメントを通過し、charを文字と照合します(これは、デバッガーのcharに対するある種の暗号化ですか?)
ただし、まったく同じ#includesがut_chordに含まれており、間隔の評価に失敗します
これがインターバルutとコードutのサンプルです
ut_interval
#include "../common/namespace_notes.h"
#include "../common/note.h"
#include "../common/interval.h"
#define BOOST_TEST_MODULE IntervalTest
#include <boost/test/auto_unit_test.hpp>
#define TEST_IVL(i, dist, itv, q, n) \
BOOST_CHECK(i.distance() == dist); \
BOOST_CHECK(i.interval() == i.itv); \
BOOST_CHECK(i.quality() == i.q); \
BOOST_CHECK(i.name() == n)
BOOST_AUTO_TEST_CASE(INTERVAL_UNISONS)
{
// make some notes
Note C = Note('C');
Note Cs = Note('C', Cs.SHARP);
Note Cds = Note('C', Cds.DSHARP);
Note Cf = Note('C', Cf.FLAT);
Note Cdf = Note('C', Cdf.DFLAT);
// make some intervals
Interval PUnison = Interval(C, C);
Interval AugUnison = Interval(C, Cs);
Interval Aug2Unison = Interval(C, Cds);
Interval DimUnison = Interval(C, Cf);
Interval Dim2Unison = Interval(C, Cdf);
// make sure members are accurate
TEST_IVL(PUnison, 0, UNISON, PER, "Perfect Unison");
BOOST_CHECK(PUnison.isPerfect());
TEST_IVL(AugUnison, 1, UNISON, AUG, "Augmented Unison");
BOOST_CHECK(AugUnison.isAugmented());
TEST_IVL(Aug2Unison, 2, UNISON, AUG, "Augmented Unison");
BOOST_CHECK(AugUnison.isAugmented());
TEST_IVL(DimUnison, 1, UNISON, AUG, "Augmented Unison");
BOOST_CHECK(DimUnison.isAugmented());
TEST_IVL(Dim2Unison, 2, UNISON, AUG, "Augmented Unison");
BOOST_CHECK(Dim2Unison.isAugmented());
}
ut_chord
#include "../common/namespace_notes.h"
#include "../common/note.h"
#include "../common/interval.h"
#include "../common/chord.h"
#define BOOST_TEST_MODULE ChordTest
#include <boost/test/auto_unit_test.hpp>
#include <memory>
BOOST_AUTO_TEST_CASE(ChordConstructor)
{
typedef std::shared_ptr<Note> nt;
nt C = nt(new Note('C'));
nt E = nt(new Note('E'));
nt G = nt(new Note('G'));
nt B = nt(new Note('B'));
Interval PUnison = Interval(*C, *C); // cannot determine this interval
Chord C7 = Chord(C , E, G, B);
Chord C72 = Chord(B, G, E, C);
Chord C73 = Chord(E, G, C, B);
}