Linux上で稼動するあるC++のプログラムを作るのに、
みんなで使えるような、共通クラスを作りたいと思っています。
クラス自体の作り方(プログラムコード)はだいたい分かるのですが、
それをどのような形(lib?またはアーカイブ?またはdll?)で
配布すると、みんなが使いやすいものになるのかが分かりません。
手順など、どなたか教えてください。
私が何とか予想できる手順を以下に書きます。

(1)普通にクラスを作成する。(例えばaaa.cppと言う名前のファイルに)
  public class AAA{
public:
void init();
void clean();
private:
int elems;
}
void AAA::init(){
elems = 0;
}
void AAA::clean(){
elems = 0;
}
※この時点でクラスの定義部分だけをヘッダーファイルとして
  別ファイルにしておいた方が良いのでしょうか?

(2)このクラスをコンパイルして、みんなに提供できる何らかの形にする。
 ※ここがよく分かりません!!
 ※”.a”というアーカイブを作成する方法は知っています。
  これを作れば良いのでしょうか?

(3)出来上がった共通クラスをどうにかして、他の人のプログラムで使えるようにする。
 ※予想としては、(1)で作ったクラス定義のヘッダーファイルを
  includeする(のかな?)
  それから、コンパイルする時にmakefileの中で(2)で作った
  ライブラリ(?)を一緒にリンクする(のかな?)
 ※プログラム中では、いきなり
   AAA testBuf = new AAA();
testBuf.init();
などと使えるのでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (2件)

> 私が何とか予想できる手順を以下に書きます。



やってみれば、すぐ分かることなのに。というのも、orange_pie さんが考えて
いる通りで、実現できるから、です。

他のプログラム(コンパイル単位)で必要なのは、クラスの宣言です。なので、

class AAA{
public:
void init();
void clean();
private:
int elems;
};

は、ヘッダファイル aaa.h に記述します。クラスのメソッドの定義は、aaa.cpp に
記述します。

#include "aaa.h"

void AAA::init()
{
elems = 0;
}
void AAA::clean()
{
elems = 0;
}

で、その定義をコンパイルしてアーカイブに入れておきます。(知っているようですが)例えば、

% gcc -c aaa.cpp
% ar -r libaaa.a aaa.o

使う側では、ヘッダファイルをインクルードするだけで、コンパイルが通ります。

#include "aaa.h"

int main()
{
AAA *testBuf = new AAA();
testBuf->init();
return 0;
}

リンクする際には、先程作成したアーカイブが必要になります。

% gcc -o test_aaa test_aaa.cpp -laaa


ね、質問に書いてあるままでしょう?

# 細かい記述ミスなんかは訂正をしています
    • good
    • 0
この回答へのお礼

すてき、すてき!!(^○^)
分かりやすくて素敵!!
ありがとうございます。早速やってみます。
<他のプログラム(コンパイル単位)で必要なのは、クラスの宣言です。>とか
<ヘッダファイル aaa.h に記述します。>とか
<クラスのメソッドの定義は、aaa.cpp に記述します。 >とか、
<使う側では、ヘッダファイルをインクルードするだけで、コンパイルが通ります。 >とか、

知りたい事の全てが、これらの言葉ですんなり理解できました。
「痒いところに手が届いちゃった」という感じです。
こんな長ったらしくて要点がまとめられない質問から
知りたい事を分かってもらえたのがとっても嬉しいです。
ありがとうございます。

お礼日時:2001/09/27 15:13

> 知りたい事の全てが、これらの言葉ですんなり理解できました。



解答をした甲斐があった、というもんです :-)

蛇足かもしれませんが、先の回答は、あくまでも、最初の取っ掛かり部分でしかないということを
言っておきます。

共通のクラスが増えてゆくことで、

・あるクラスが別のクラスと関連を持っている
・Cインターフェースの関数
・インライン関数
・テンプレートクラス

なんてことがでてくるので。

まあ、そのときには、また質問をしてみればいいんですけどね。


とりあえず、さっきの回答をひとつだけ補足しておきます。

インクルードファイルの二重読み込みの防止だけはしておいた方が良いでしょう。
インクルードファイルの内容を以下のような感じのマクロで括っておきます。

#ifndef AAA_DEFINED
#define AAA_DEFINED

class AAA {
public:
void init();
void clean();
private:
int elems;
};

#endif /* AAA_DEFINED */

/usr/include 配下のヘッダファイルなんかを見てみると、だいたいこんな感じ
になっているのが分かると思います。
    • good
    • 0
この回答へのお礼

そうですね。
>共通のクラスが増えてゆくことで、
>・あるクラスが別のクラスと関連を持っている
>・Cインターフェースの関数
>・インライン関数
>・テンプレートクラス
>なんてことがでてくるので。

ム(-"-;)むむむ。。。。

>まあ、そのときには、また質問をしてみればいいんですけどね。
そうします。今は難しいことは後回しにして、基本的な使い方だけ
会得することにします。


>インクルードファイルの二重読み込みの防止だけはしておいた方が良いでしょう。
そうですね。いつもはやっていますが、今はまだヘッダーファイルを配布した時の事まで考えていませんでした。そうします。

ありがとうございました。

お礼日時:2001/09/27 15:41

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qvoid main(void){...}だとDosWindowが開くので

わざわざWindowsアプリにして以下のようにするしかないのでしょうか?

LONG WINAPI WinProcedure(HWND hW,UINT wM,UINT wP,LONG lP)
{
//ここに宣言を置く
switch(wM)
{
case WM_CREATE:
//ここに処理を置く
return 0;
default:
return(DefWindowProc(hW,wM,wP,lP));
}
}
WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int nCS)
{
WNDCLASSwc;
HWNDhW,hPW;
MSGms;

wc.lpszClassName="goo";
wc.lpfnWndProc=(WNDPROC)WinProcedure;
wc.hInstance=hI;
wc.style=CS_HREDRAW|CS_VREDRAW;
wc.cbClsExtra=NULL;
wc.cbWndExtra=NULL;
wc.hIcon=LoadIcon(NULL,IDI_EXCLAMATION);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName=NULL;
RegisterClass(&wc);
hW=CreateWindow
(
"goo",
"教えて!goo",
WS_OVERLAPPED,
0,
0,
640,
456,
NULL,
NULL,
hI,
NULL
);
ShowWindow(hW,nCS);
UpdateWindow(hW);
while(GetMessage(&ms,NULL,NULL,NULL))
{
TranslateMessage(&ms);
DispatchMessage(&ms);
}
return (ms.wParam);
}

もっと簡単にDosWindowが開かないようにする方法はないのでしょうか?
もしないとすると上記記述でもっと簡単にできないでしょうか?

わざわざWindowsアプリにして以下のようにするしかないのでしょうか?

LONG WINAPI WinProcedure(HWND hW,UINT wM,UINT wP,LONG lP)
{
//ここに宣言を置く
switch(wM)
{
case WM_CREATE:
//ここに処理を置く
return 0;
default:
return(DefWindowProc(hW,wM,wP,lP));
}
}
WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int nCS)
{
WNDCLASSwc;
HWNDhW,hPW;
MSGms;

wc.lpszClassName="goo";
wc.lpfnWndProc=(WNDPROC)WinProcedure;
wc.hInstance=hI;
wc.style=CS_HREDRAW|CS_VREDRAW;
wc...続きを読む

Aベストアンサー

ウィンドウを開く必要がないなら、mainをWinMainに変更するだけで良いのでは? ウィンドウクラス登録、ウィンドウ作成、メッセージループ、ウィンドウプロシージャは全て不要な気がしますが。

WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int nCS)
{
  //処理内容

  return 0;
}

Qtry{}catch(){}とデストラクタの関係を教えてください。

try-catchでメモリ確保を含むクラスをスローした場合、デストラクタはどの時点で働くのか、教えてください。たとえば、↓の使いかたは大丈夫でしょうか?

【1】
try{
 throw(CError(100, "エラー情報"));
}catch(CError& err){
 //ここでerrを参照しても問題ないのでしょうか?
}

【2】
try{
 CError err(100, "エラー情報");
 throw(err); // (1)
}catch(CError& err){
 //ここでerrを参照しても問題ないのでしょうか?
 //まだデストラクタはちゃんと動作するのでしょうか?
 //catchが呼び出し元のメンバであったりしても大丈夫なのでしょうか?
}

宜しくお願いします。

Aベストアンサー

【1】【2】どちらの場合も問題がありません。
コンパイラが必要に応じてerrオブジェクトのコピーを作成します。
デストラクタが呼び出されるタイミングはコンパイラに依存するところもあると思いますが、
例えばVC7.1では【2】は以下のように動作します。
(1) errオブジェクトのコンストラクタが呼び出される
(2) CErrorクラスのテンポラリオブジェクト(以下a)のコピーコンストラクタが呼び出される。
(3) errオブジェクトのデストラクタが呼び出される
(4) catch文まで到達
(5) aオブジェクトのデストラクタが呼び出される。

VC7.1では、【1】は以下のように動作します。
(1) errオブジェクトのコンストラクタが呼び出される
(2) catch文まで到達
(3) errオブジェクトのデストラクタが呼び出される。

コンパイラがオブジェクトのコピーを省略しているようです。

Q{x = x>y ? x:y; return x;}

#include <iostream>
using namespace std;

inline int max(int x, int y){x = x>y ? x:y; return x;}

int main()
{
int num1, num2, ans;

cout << "2つの整数を入力して。\n";
cin >> num1 >> num2;

ans = max(num1, num2);

cout << "最大値は" << ans << "です。\n";

return 0;
}
の{x = x>y ? x:y; return x;}の部分の意味が解りません。

Aベストアンサー

inline int max(int x, int y){x = x>y ? x:y; return x;}
これを普通に関数で書くと

int max(int x, int y)
{
x = x>y ? x:y;
return x;
}

です。

x = 部分は右辺の結果が代入されます。これはわかりますよね。
x>y?x:y;
と書くと?より左にある条件式を判定し、その結果が真である場合は:で区切られた左側の値を、偽である場合は右の値を帰します。
x>yが真であればxを、偽であればyを返します。
それが、左辺値xに代入され、関数の戻り値として帰ります。

従って、2つの値をこの関数に入れると、大きいほうの値が帰ることになります。

Qint main()、void main()、void main(void)、int main(void)

今日、大学でC言語の講義の時間、先生が、

#include <stdio.h>

void main(void){

}

と宣言してプログラムを書くと教えていました。
main関数には、
main()
void main()
void main( void )
int main()
int main( void )

と、人によりいくつかの描き方があったりします。
どれが本当は正しいのでしょうか?
void mainはすべきではないとなんかの本で読んだのですが・・。

Aベストアンサー

通称C89という以前の言語規格(現行コンパイラの多くが準拠)では、下記のいずれかが正しい。
int main(int argc, char *argv[])
int main(void)

但し、最新のC言語規格(通称C99)では、
<ISO/IEC9899:1999>
or in some other implementation-defined manner.
</ISO/IEC9899:1999>
となっているので、処理系が戻り値のvoidを認めていればvoidも可。
# 組込み系などで戻り値を使わない環境もあるためでしょうか。

なので、コンパイラのマニュアルで戻り値のvoidにしていい/しろと書いてない限り、
voidは言語仕様的には正しくない。(でも動くものもある)

Qchar AA[]{"全角文字"};から"全"という一字を取り出したい

 今晩は、Cの初心者です、宜しくお願いします。
 全角文字の入ったchar AA[]{"全角文字"};から"全"という文字一字を取り出す時にAA[0]とかくとエラーになります。
 どのようにしたら取り出せるのでしょう。
 ポインタを使う方法と使わない方法を教えて下さい。
 宜しくお願いします。

Aベストアンサー

お疲れ様です。

まずお伺いしたのがOSおよび開発するためのコンパイラです。

ロケール等の話は分かりませんが、昔のC言語で日本語を扱う場合には全角文字1文字で2個つのchar領域を使用していました。
(マルチバイト文字セットと言います。)

詳細は参考URLを参照の事。

windowsでVCと仮定した場合、charを使われていると言うことは、多分、shift-jis(シフトJIS)で文字列を扱っていると思われます。

結論として全角文字1文字だけを取り出したいという場合は、結局char2個分のデータを取り出す必要があります。

>char AA[]={'全','角'};

char AA[]="全角";
とし
>printf("%s%s\n" , AA[0],AA[1] ) ;

printf("%c%c\n" , AA[0],AA[1] ) ;
とすれば、「全」だけを表示する事が可能と思われます。

日本語を文字列で表示する為の文字コードについては
Shift-JISだけでなく、UnicodeやUTF・EUC・JISなどがあります。

もう少し詳しく記載してあるホームページはないか探してみましたが、ちょっと無理でした。

参考URL:http://marupeke296.com/CPP_charUnicodeWideChar.html

お疲れ様です。

まずお伺いしたのがOSおよび開発するためのコンパイラです。

ロケール等の話は分かりませんが、昔のC言語で日本語を扱う場合には全角文字1文字で2個つのchar領域を使用していました。
(マルチバイト文字セットと言います。)

詳細は参考URLを参照の事。

windowsでVCと仮定した場合、charを使われていると言うことは、多分、shift-jis(シフトJIS)で文字列を扱っていると思われます。

結論として全角文字1文字だけを取り出したいという場合は、結局char2個分のデータを取り出...続きを読む


人気Q&Aランキング

おすすめ情報