C++メモ
by やながわ@NDK
C++入門編
1. Hello world
2. 入力 (cin)
3. クラスをつくる
4. privateとpublic
C++応用編
1. RTE-VR5432のLEDを点灯
2. クラスの継承
3. クラスの多重継承
4. クラスの派生
5. 仮想関数
使用した環境
exeGCC MIPS Release 2.0 (Ver 2.9のもの)
PARTNER-ETU (N-wire エミュレータ)
RTE-VR5432-CB (LITTLE ENDIAN)
C++入門編
1.Hello world
最も簡単なもの
sample.cpp
#include <iostream>
main()
{
cout << "Hello World" << endl;
}
// '<< endl'は改行することです。
makefile
CXX = gcc
CXXFLAGS = -c -g -o $@
%.o : %.cpp
$(CXX) $(CXXFLAGS) $<
sample.out : sample.o
gcc -o $@ $^
注意 このプログラムを実行するには、バーチャルリンクの設定を
行って下さい。
2.入力 (cin)
ホストマシンからの入力をターゲット上のバッファに入れることができる。
#include <iostream>
main()
{
char charac[101];
cout << "文字の入力" << endl;
cin >>charac;
cout << "入力文字は" <<charac << endl;
}
プログラム実行後の
ローカル変数とコマンドウインドウの表示結果
3.クラスをつくる。
とても簡単なクラス
#include <iostream>
class Display
{
private:
char moji[11];
public:
Display(char s[]){strcpy(moji,s);}
void Hyouji(){cout<<"入力した文字は"<<moji<<"だ。"<<endl;}
};
void main()
{
char s[11];
cout<<"文字列を入力してください。"<<endl;
cin>>s;
Display Nyu(s);
cout<<"入力した文字列が配列上に生成されました。"<<endl;
Nyu.Hyouji();
}
classの説明
class Display
入力(データメンバ):配列5文字
動作(メンバ関数) :文字の表示
private:
char moji[11]; これは、他のクラスで使うことができない宣言です。
public: 他のクラスから使うことができる宣言。
Display(char s[]){strcpy(moji,s);}
データmojiに、受け取った文字列sを代入する。
注 s[] []内に数字を入れてはいけません。
この関数名はクラス名と同じにすること
(この関数をコンストラクタです。)
Hyouji()をDisplayのメンバ関数と言います。
mainの説明
Display Nyu(s);
文字列"s"をもとにしてDisplayのひとつNyuを作成します。
つまり、このNyuの作成をコンストラクタと言います。
Nyu.Hyouji();
Nyuを表示させたいときは Nyu.Hyouji();と書きます。
プログラム実行結果と変数の表示
ローカル変数ウインドウで表示しているものは、
配列s,クラスDisplay中のprivate変数moji[11],クラスDisplay中の文字列name
それと、クラスは構造体の親戚?なので、クラスないでのブレークポイントは張れないみたいです。
よし、インライン化をやめて、メンバ関数を外に出して定義してみよう。
#include <iostream>
class Display
{
private:
char moji[11];
public:
Display(char s[]);
void Hyouji();
};
Display::Display(char s[]){strcpy(moji,s);}
void Display::Hyouji(){cout<<"入力した文字は"<<moji<<"だ。"<<endl;}
void main()
{
char s[11];
cout<<"文字列を入力してください。"<<endl;
cin>>s;
Display Nyu(s);
cout<<"入力した文字列が配列上に生成されました。"<<endl;
Nyu.Hyouji();
}
4.privateとpublic
privateとpublicの違いを上記のプログラムをもとに記します。
#include <iostream>
class Display
{
public:
char moji[11];
Display(char s[]){strcpy(moji,s);}
void Hyouji(){cout<<"入力した文字は"<<moji<<"だ。"<<endl;}
};
void main()
{
char s[11];
cout<<"文字列を入力してください。"<<endl;
cin>>s;
Display Nyu(s);
cout<<"入力した文字列が配列上に生成されました。"<<endl;
cout<<"入力した文字は"<<Nyu.moji<<"だ。"<<endl;
}
classのなかの変数を全てpublicにしています。
そーすると、メンバ関数を呼びださなくても、mainの中で、直接変数mojiをさわれます。
C++応用編
1.RTE-VR5432-CBのLEDを点灯させる
サンプルプログラム
class led{
public:
int address0;
int mem0;
};
led loop[]={
{0xb8002000,0xfffff7ff},
{0xb8002000,0xfffffff7},
{0xb8002000,0xfffffffb},
{0xb8002000,0xfffffffd},
{0xb8002000,0xfffffffe},
{0xb8002000,0xfffffeff},
{0xb8002000,0xfffeffff},
{0xb8002000,0xfeffffff},
{0xb8002000,0xdfffffff},
{0xb8002000,0xefffffff},
{0xb8002000,0xf7ffffff},
{0xb8002000,0xfff7ffff},
{0xb8002000,0xffffffff},
{0xb8002000,0x0},
};
#include <iostream>
class Loop
{
private:
int i;
public:
int j;
void Hloop();
};
void Loop::Hloop()
{
for(i=0;i<50000;i++)
{
*(unsigned *)loop[j].address0=loop[j].mem0;
}
}
main()
{
while(1)
{
Loop L7seg;
for(L7seg.j=0;L7seg.j<12;L7seg.j++)
{
L7seg.Hloop();
}
}
}
解説
Cからの移植なので、あまりC++らしくないな。
L7seg : クラスLoopをL7segとしてつかう。(構造体変数のようなもの)
L7seg.j=0 : クラスLoop中の変数jを0
L7seg.Hloop(); クラスLoop中のHloop関数を実行。
クラスの説明
class Loop
データメンバ i : LED点灯ウエイトの数 (private)
j : LED点灯パターンの数 (mainの中で定義するのでpublic)
メンバ関数 Hloop: LEDの点灯
実行結果
main()関数内でプログラムをブレークすると変数が以下のように現れます。
しかし、非インライン化された関数Hloop()内で、プログラムを止めると
下記のように定義していない?ポインタ(this)が現れます。
これは、thisというポインタが自動的に定義されているみたいです。
this は,静的でないメンバー関数の本体のローカル変数です。
これは,呼び出された関数自体のオブジェクトを指すポインタです。
?よくわからんな?
別の言い方をすると、
thisポインタとは、メンバ関数が呼び出された時のインスタンス自信の
ポインタを言います。
インスタンスとは実体のことで、クラスから作られるものです。
クラスからインスタンス(実体)を作ることをコンストラクトといいます。
2.クラスの継承(インヘリタンス)
元のクラスの性質を保ったまま新しいクラスを作る。
言い方を変えると、元のクラスの部分を修正しないで、
クラスの機能を拡張する。(差分コーディングが可能)
サンプルプログラム
前述のプログラムとの変更点を紫色で示します。
class led{
public:
int address0;
int mem0;
};
led loop[]={
{0xb8002000,0xfffff7ff},
{0xb8002000,0xfffffff7},
{0xb8002000,0xfffffffb},
{0xb8002000,0xfffffffd},
{0xb8002000,0xfffffffe},
{0xb8002000,0xfffffeff},
{0xb8002000,0xfffeffff},
{0xb8002000,0xfeffffff},
{0xb8002000,0xdfffffff},
{0xb8002000,0xefffffff},
{0xb8002000,0xf7ffffff},
{0xb8002000,0xfff7ffff},
{0xb8002000,0xffffffff},
{0xb8002000,0x0},
};
#include <iostream>
class Loop
{
private:
int i;
public:
int j;
void Hloop();
};
void Loop::Hloop()
{
for(i=0;i<50000;i++)
{
*(unsigned *)loop[j].address0=loop[j].mem0;
}
}
class yea: public Loop
{
private:
int ii;
int address1;
int mem1;
public:
void Yloop();
};
void yea::Yloop()
{
address1=0xb8002000;
mem1=0x998688af;
for(ii=0;ii<50000;ii++)
{
*(unsigned *)address1=mem1;
}
}
main()
{
while(1)
{
yea L7seg;
for(L7seg.j=0;L7seg.j<12;L7seg.j++)
{
L7seg.Hloop();
}
L7seg.Yloop();
}
}
解説
7seg LEDを点灯させるプログラムに、点灯パターンを追加。
クラスの説明
class yea
データメンバ i : LED点灯ウエイトの数 (private)
j : LED点灯パターンの数 (mainの中で定義するのでpublic)
ii : LED点灯ウエイトの数 (private)
address1 : LEDポートのアドレス
mem1 : 点灯データ
メンバ関数 Yloop: LEDの点灯
Hloop: LEDの点灯
今回のような変更を特化と言うらしい。
3.クラスの多重継承
前出のプログラムに、さらに別の機能を加えます。
(LEDの点灯パターン"2000"をさらに追加)
長くなるので、変更点のみを記載します。
class mille: public yea
{
private:
int ii;
int address2;
int mem2;
public:
void Xloop();
};
void mille::Xloop()
{
address2=0xb8002000;
mem2=0xa4a3a3a3;
for(ii=0;ii<500000;ii++)
{
*(unsigned *)address2=mem2;
}
}
main()
{
while(1)
{
mille L7seg;
for(L7seg.j=0;L7seg.j<12;L7seg.j++)
{
L7seg.Hloop();
}
L7seg.Yloop();
L7seg.Xloop();
}
}
つまり、class milleを記述してmainのコンストラクトのところと
メンバ関数を実際に呼びだすところを加えただけでできてしまいます。
4.クラスの派生
作成中
5.仮想関数
仮想関数とは、
「オブジェクトが基底クラスのポインタなどで示されている場合にも
正しく呼び出される関数」