質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.44%
MFC

MFC (Microsoft Fouondation Class)とは、MicrosoftがVC++用に開発したWindows用アプリケーションのフレームワークです。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

2837閲覧

C++(MFC)で自作クラスをクラス定義(.h)と関数実装(.cpp)に分割したい

exp

総合スコア13

MFC

MFC (Microsoft Fouondation Class)とは、MicrosoftがVC++用に開発したWindows用アプリケーションのフレームワークです。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/02/23 06:34

前提・実現したいこと

C++(MFC)でsqliteをDLLとして読み込んで使いたいです。
DLLの読み込み処理をクラスにまとめてヘッダファイル(.h)に書いた際は動作しましたが、
そのクラスのコンストラクタの実装を.cppに分割したところコンパイルが通らなくなりました。
開発環境は次の通りです

該当のソースコード

ダイアログにはボタンが一つあり、それが押されたときにsqliteのDLL読み込んで.dbファイルを作ります
sqliteを扱うクラスはSaverという名前でsaver.hにクラス定義、saver.cppにコンストラクタの実装、と分割したいと考えています。

saver.h

c++

1#pragma once 2 3#include "sqlite3.h" 4#include "stdafx.h" 5 6 7// sqlite3.dll内関数ポインタ型定義 8typedef int(__cdecl * pOpen)(char *, sqlite3 **); 9typedef int(__cdecl * pExec)(sqlite3 *, const char *, sqlite3_callback, void *, char **); 10typedef int(__cdecl * pGetTable)(sqlite3 *, const char *, char ***, int *, int *, char **); 11typedef int(__cdecl * pFreeTable)(char **); 12typedef int(__cdecl * pClose)(sqlite3 *); 13 14class Saver { 15 16 17 18public: 19 Saver(); 20 21 22public: 23 24 // 関数ポインタ変数 25 pOpen sqlite3_open; 26 pExec sqlite3_exec; 27 pGetTable sqlite3_get_table; 28 pFreeTable sqlite3_free_table; 29 pClose sqlite3_close; 30 31 32 HINSTANCE hDll; 33 sqlite3 *db; 34 char *err; 35 char **result; 36 int row, col; 37 CString str; 38 39};

saver.cpp

c++

1#include "saver.h" 2#include "stdafx.h" 3#include <windows.h> 4Saver::Saver(){ 5 6 AfxMessageBox(_T("saver constructed")); 7 // sqlite3.dllをロード 8 hDll = LoadLibrary("sqlite3"); 9 if (hDll == NULL) { 10 FreeLibrary(hDll); 11 AfxMessageBox(_T("dll cant be loaded.")); 12 return; 13 } 14 15 16 // sqlite3関数のアドレスを取得 17 sqlite3_open = (pOpen)GetProcAddress(hDll, "sqlite3_open"); 18 sqlite3_exec = (pExec)GetProcAddress(hDll, "sqlite3_exec"); 19 sqlite3_get_table = (pGetTable)GetProcAddress(hDll, "sqlite3_get_table"); 20 sqlite3_free_table = (pFreeTable)GetProcAddress(hDll, "sqlite3_free_table"); 21 sqlite3_close = (pClose)GetProcAddress(hDll, "sqlite3_close"); 22 23 24 25 // データベースファイルを作成 26 sqlite3_open("test.db", &db); 27 28 // テーブル作成 29 sqlite3_exec(db, "create table test(num integer,name string);", NULL, NULL, &err); 30 // データを格納 31 sqlite3_exec(db, "insert into test values(1,'test1');", NULL, NULL, &err); 32 33 34 // データベースファイルを閉じる 35 sqlite3_close(db); 36 37 38} 39

memoDlg.cpp

文字数が足りないので抜粋です。
デフォルトの状態からボタンを追加しており、ヘッダのインクルードとボタン押下時のクラスを実体化を追加しています。

c++

1 2// memoDlg.cpp : 実装ファイル 3// 4 5#include "stdafx.h" 6#include "memo.h" 7#include "memoDlg.h" 8#include "afxdialogex.h" 9 10#include "saver.h" 11

c++

1void CmemoDlg::OnBnClickedadd() 2{ 3 // TODO: ここにコントロール通知ハンドラー コードを追加します。 4 Saver sv; 5}

エラー

1>------ ビルド開始: プロジェクト: memo, 構成: Debug x64 ------ 1>saver.cpp 1>c:\users\master\desktop\memo\memo\saver.cpp(6): error C2653: 'Saver': 識別子がクラス名でも名前空間名でもありません。 1>c:\users\master\desktop\memo\memo\saver.cpp(6): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません 1>c:\users\master\desktop\memo\memo\saver.cpp(10): error C2065: 'hDll': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(11): error C2065: 'hDll': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(12): error C2065: 'hDll': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(14): warning C4508: 'Saver': 関数に戻り値の型が指定されていません。戻り値を void 型と見なします。 1>c:\users\master\desktop\memo\memo\saver.cpp(19): error C2065: 'sqlite3_open': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(19): error C2065: 'pOpen': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(19): error C2146: 構文エラー: ';' が、識別子 'GetProcAddress' の前に必要です。 1>c:\users\master\desktop\memo\memo\saver.cpp(19): error C2065: 'hDll': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(20): error C2065: 'sqlite3_exec': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(20): error C2065: 'pExec': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(20): error C2146: 構文エラー: ';' が、識別子 'GetProcAddress' の前に必要です。 1>c:\users\master\desktop\memo\memo\saver.cpp(20): error C2065: 'hDll': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(21): error C2065: 'sqlite3_get_table': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(21): error C2065: 'pGetTable': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(21): error C2146: 構文エラー: ';' が、識別子 'GetProcAddress' の前に必要です。 1>c:\users\master\desktop\memo\memo\saver.cpp(21): error C2065: 'hDll': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(22): error C2065: 'sqlite3_free_table': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(22): error C2065: 'pFreeTable': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(22): error C2146: 構文エラー: ';' が、識別子 'GetProcAddress' の前に必要です。 1>c:\users\master\desktop\memo\memo\saver.cpp(22): error C2065: 'hDll': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(23): error C2065: 'sqlite3_close': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(23): error C2065: 'pClose': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(23): error C2146: 構文エラー: ';' が、識別子 'GetProcAddress' の前に必要です。 1>c:\users\master\desktop\memo\memo\saver.cpp(23): error C2065: 'hDll': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(28): error C2065: 'db': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(28): error C3861: 'sqlite3_open': 識別子が見つかりませんでした 1>c:\users\master\desktop\memo\memo\saver.cpp(31): error C2065: 'db': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(31): error C2065: 'err': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(31): error C3861: 'sqlite3_exec': 識別子が見つかりませんでした 1>c:\users\master\desktop\memo\memo\saver.cpp(33): error C2065: 'db': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(33): error C2065: 'err': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(33): error C3861: 'sqlite3_exec': 識別子が見つかりませんでした 1>c:\users\master\desktop\memo\memo\saver.cpp(37): error C2065: 'db': 定義されていない識別子です。 1>c:\users\master\desktop\memo\memo\saver.cpp(37): error C3861: 'sqlite3_close': 識別子が見つかりませんでした 1>c:\users\master\desktop\memo\memo\saver.cpp(40): error C2617: 'Saver': 'return' ステートメントが正しくありません。 1>c:\users\master\desktop\memo\memo\saver.cpp(6): note: 'Saver' の宣言を確認してください 1>memoDlg.cpp 1>コードを生成中... 1>スキップ中... (関連する変更は検出されませんでした) 1>memo.cpp 1>プロジェクト "memo.vcxproj" のビルドが終了しました -- 失敗。 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

試したこと

saver.hsaver.cppの内容を書き、saver.cpp内はコメントアウトした場合は想定通りに動きます。

saver.h

c++

1#pragma once 2 3#include "sqlite3.h" 4#include "stdafx.h" 5 6 7// sqlite3.dll内関数ポインタ型定義 8typedef int(__cdecl * pOpen)(char *, sqlite3 **); 9typedef int(__cdecl * pExec)(sqlite3 *, const char *, sqlite3_callback, void *, char **); 10typedef int(__cdecl * pGetTable)(sqlite3 *, const char *, char ***, int *, int *, char **); 11typedef int(__cdecl * pFreeTable)(char **); 12typedef int(__cdecl * pClose)(sqlite3 *); 13 14class Saver { 15 16 17 18public: 19 Saver(); 20 21 22public: 23 24 // 関数ポインタ変数 25 pOpen sqlite3_open; 26 pExec sqlite3_exec; 27 pGetTable sqlite3_get_table; 28 pFreeTable sqlite3_free_table; 29 pClose sqlite3_close; 30 31 32 HINSTANCE hDll; 33 sqlite3 *db; 34 char *err; 35 char **result; 36 int row, col; 37 CString str; 38}; 39 40Saver::Saver() { 41 42 AfxMessageBox(_T("saver constructed")); 43 // sqlite3.dllをロード 44 hDll = LoadLibrary("sqlite3"); 45 if (hDll == NULL) { 46 FreeLibrary(hDll); 47 AfxMessageBox(_T("dll cant be loaded.")); 48 return; 49 } 50 51 52 // sqlite3関数のアドレスを取得 53 sqlite3_open = (pOpen)GetProcAddress(hDll, "sqlite3_open"); 54 sqlite3_exec = (pExec)GetProcAddress(hDll, "sqlite3_exec"); 55 sqlite3_get_table = (pGetTable)GetProcAddress(hDll, "sqlite3_get_table"); 56 sqlite3_free_table = (pFreeTable)GetProcAddress(hDll, "sqlite3_free_table"); 57 sqlite3_close = (pClose)GetProcAddress(hDll, "sqlite3_close"); 58 59 60 61 // データベースファイルを作成 62 sqlite3_open("test.db", &db); 63 64 // テーブル作成 65 sqlite3_exec(db, "create table test(num integer,name string);", NULL, NULL, &err); 66 // データを格納 67 sqlite3_exec(db, "insert into test values(1,'test1');", NULL, NULL, &err); 68 69 70 // データベースファイルを閉じる 71 sqlite3_close(db); 72 73 74}

質問のMFCのコードではなぜ、クラスやそのメンバ変数を見つけられないのでしょうか?
よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KoichiSugiyama

2019/02/23 07:39

プロジェクトをビルドするのではなく、単純にsaver.cppをコンパイルした場合どうなりますか? もし同じエラーが出るとしたら、saver.hとsaver.cppのどちらかに問題があると絞り込めると思います。 ヘッダにコピーしてビルドが通った状態のものから、再度*.hと*.cppに分けても同じエラーになりますか
exp

2019/02/23 07:47

情報ありがとうございます! .cppのみをコンパイルしてみると、エラーはでませんでした。
guest

回答3

0

ベストアンサー

こんにちは。

外しているかも知れませんが、プリコンパイル済みヘッダで問題が起きている可能性があります。

#include "stdafx.h"の前にはコメント以外書いて大丈夫でしたっけ? stdafx.hがプリコンパイルされた後で、その前にある定義が変更されると問題が発生しそうな気がします。それが原因であればリビルドすれば良いはずです。

ただ、過去リビルドでも改善しなかったことがあります。その時は、プリコンパイル済みヘッダを「使用しない」と設定して逃げました。設定方法は「プリコンパイル済みヘッダ」で検索すると多数でてきます。

投稿2019/02/23 07:48

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

exp

2019/02/23 07:55

情報ありがとうございます! コンストラクタの前方に`class Saver;`を追加して解決できました。 プリコンパイル済みヘッダについては知らなかったので、今後の参考にさせて頂きます。
Chironian

2019/02/23 08:00

う~ん、少なくともそれは正しい対策ではないですよ。 本質的に解決出来るはずがない対処なので、後日、謎のトラブルに巻き込まれるリスクが結構あると思います。
exp

2019/02/23 08:18

おっしゃる通り、リビルドしてみたところ、`class Saver;`がなくても動作しました。 先ほど解決したと思ったのは`class Saver;`は関係なく、 気づかないうちにリビルドされていたということでしょうか? 以後`#include "stdafx.h"`を最初に書くようにします。 ご指摘ありがとうございます!
guest

0

この方法では解決していませんでした。
~~saver.cppでコンストラクタの実装より前に次を追加したところ解決しました。
前方宣言というのですね。
~~

c++

1class Saver;

ご協力頂いたy_waiwaiさん、KoichiSugiyamaさん、Chironianさん、ありがとうございました。

投稿2019/02/23 07:49

編集2019/02/23 08:27
exp

総合スコア13

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Saver.hはどこに入れてますか?
Saver.cppは、そのSaver.h ではないファイルを読んでいるんじゃないでしょうか

C/C++では、すでに定義されたものしか見つけることができません。
そのキーワードを使用するときには、それより以前(それより手前の行)で定義されていなければなりません。

投稿2019/02/23 06:40

編集2019/02/23 06:51
y_waiwai

総合スコア87836

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

exp

2019/02/23 07:12

ご回答ありがとうございます! saver.hは.cpp等と同じ階層にありました。 もしやと思い、#include "./saver.h"のようにしてみましたが同様の結果でした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.44%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問