4: data abstractionpds15.egloos.com/pds/200911/25/21/chapter_4_2.pdf · thinking in c++ page 6...
TRANSCRIPT
4: Data Abstraction4: Data Abstraction
김동원김동원김동원김동원
2003.02.12
Thinking in C++ Page 1
Overview
• Abstract data typing
• Object details
• Header file etiquette
• Nested structures
• Global scope resolution
Thinking in C++ Page 2
Abstract data typing
• The ability to package data with functions
– Allows you to create a new data type
– Called encapsulation
• abstract data type
– Even though it acts like a real, built-in data type, we refer to it
– It allows us to abstract a concept from the problem spaceinto the solution space
• object.memberFunction(arglist)
– Calling a member function for an object
– referred to as sending a message to an object
Thinking in C++ Page 3
Object details
• The size of a struct
– The combined size of all of its members
– Sometimes when the compiler lays out a struct, it adds extra bytes
� This may increase execution efficiency
Thinking in C++ Page 4
Object details (example)
#include "CLib.h"
#include "CppLib.h"
#include <iostream>
using namespace std;
struct A
{
int i[100];
};
struct B
{
void f();
};
void B::f()
{ }
Thinking in C++ Page 5
Object details (example)
int main()
{
cout << "sizeof struct A = " << sizeof(A)
<< " bytes" << endl;
cout << "sizeof struct B = " << sizeof(B)
<< " bytes" << endl;
cout << "sizeof CStash in C = "
<< sizeof(CStash) << " bytes" << endl;
cout << "sizeof Stash in C++ = "
<< sizeof(Stash) << " bytes" << endl;
}
Thinking in C++ Page 6
Header file etiquette
• Importance of header files
• The multiple-declaration problem
• The preprocessor directives #define, #ifdef, and #endif
• A standard for header files
• Namespaces in headers
• Using headers in projects
Thinking in C++ Page 7
Header file etiquette
• The header file
– tells the compiler what is available in your library
– has the interface specification
• You can use the library even if you only possess the header file along with the object file or library file
– Don’t need the source code for the cpp file
Thinking in C++ Page 8
Importance of header files
• In the past
– People would sometimes do this to speed up the compiler just a bit by avoiding the task of opening and including the file
• In the C language
– Allows you the option of ignoring the header file and simply declaring the function by hand
• In the C++ language
– must include the header file everywhere a struct is used and where struct member functions are defined
– The compiler will give an error message if you try to call a regular function, or to call or define a member function, without declaring it first
– By enforcing the proper use of header files, the language ensures consistency in libraries, and reduces bugs by forcing the same interface to be used everywhere
Thinking in C++ Page 9
Certain issues when the using header file
• First issue
– concerns what you can put into header files
– The basic rule is only declarations
� Only information to the compiler but nothing that allocates storage by generating code or creating variables
� Why
• The header file will typically be included in several translation units in a project
• If storage for one identifier is allocated in more than one place, the linker will come up with a multiple definition error
Thinking in C++ Page 10
Certain issues when the using header file (The multiple-declaration problem)
• The second issue
– When you put a struct declaration in a header file, it is possible for the file to be included more than once in a complicated program
– To prevent this error when multiple header files are included
� You need to build some intelligence into your header files using the preprocessor
– Both C and C++
� Allow you to redeclare a function, as long as the two declarations match
� Will not allow the redeclaration of a structure
Thinking in C++ Page 11
The preprocessor directives#define, #ifdef, and #endif
• The preprocessor directive #define can be used to create compile time flags
#define FLAG
or you can give it a value
#define PI 3.14159
• The label can now be tested by the preprocessor to see if it has been defined
#ifdef FLAG
• This inclusion stops when the preprocessor encounters the statement
#endif // FLAG
Thinking in C++ Page 12
A standard for header files
• In each header file
– You should first check to see if this header has already been included in this particular cpp file
#ifndef HEADER_FLAG
#define HEADER_FLAG
// Type declaration here...
#endif // HEADER_FLAG
Thinking in C++ Page 13
A standard for header files (example)
#ifndef SIMPLE_H
#define SIMPLE_H
struct Simple {
int i,j,k;
initialize() { i = j = k = 0; }
};
#endif // SIMPLE_H ///:~
Thinking in C++ Page 14
Namespaces in headers
• using namespace std;
– allows the names in the Standard C++ library to be used without qualification
• The using directive
– eliminates the protection of that particular namespace
– The effect lasts until the end of the current compilation unit
– This loss of namespace protection
• In short: don’t put using directives in header files
Thinking in C++ Page 15
Using headers in projects
• Put the declaration for each type or group of associated types in a separate header file
• Define the functions for that type in a translation unit
• When you use that type, you must include the header file to perform the declarations
Thinking in C++ Page 16
Nested structures
• A structure within another structure
Thinking in C++ Page 17
Nested structures (example)
#ifndef STACK_H#define STACK_Hstruct Stack {
struct Link {void* data;Link* next;void initialize(void* dat, Link* nxt);
}* head;void initialize();void push(void* dat);void* peek();void* pop();void cleanup();
};#endif // STACK_H ///:~
Thinking in C++ Page 18
Nested structures (example)
#include "Stack.h"#include "../require.h"using namespace std;void Stack::Link::initialize(void* dat, Link* nxt) {
data = dat;next = nxt;
}void Stack::initialize() { head = 0; }void Stack::push(void* dat) {
Link* newLink = new Link;newLink->initialize(dat, head);head = newLink;
}
Thinking in C++ Page 19
Nested structures (example)
void* Stack::peek() {
require(head != 0, "Stack empty");return head->data;
}void* Stack::pop() {
if(head == 0) return 0;void* result = head->data;Link* oldHead = head;head = head->next;delete oldHead;return result;
}
void Stack::cleanup() {require(head == 0, "Stack not empty");
}
Thinking in C++ Page 20
Nested structures (example)
#include "Stack.h"#include "../require.h"#include <fstream>#include <iostream>#include <string>using namespace std;int main(int argc, char* argv[]) {
requireArgs(argc, 1); // File name is argumentifstream in(argv[1]);assure(in, argv[1]);Stack textlines;textlines.initialize();string line;// Read file and store lines in the Stack:while(getline(in, line))textlines.push(new string(line));// Pop the lines from the Stack and print them:
Thinking in C++ Page 21
Nested structures (example)
string* s;
while((s = (string*)textlines.pop()) != 0) {
cout << *s << endl;
delete s;
}
textlines.cleanup();
}
Thinking in C++ Page 22
Global scope resolution
• The scope resolution operator
– Gets you out of situations in which the name the compiler chooses by default (the “nearest” name) isn’t what you want
Thinking in C++ Page 23
Global scope resolution (example)
int a;void f() {};struct S {
int a;void f();
};void S::f() {
::f(); // Would be recursive otherwise!::a++; // Select the global aa--; // The a at struct scope
}int main() {S s; f();
}