Compare commits
No commits in common. "58b6c7c644a410075da73066ca4558eec4be0d32" and "eb086f064b28dc6a30d8ac6ae8ca386d0dad6ba5" have entirely different histories.
58b6c7c644
...
eb086f064b
3 changed files with 3 additions and 124 deletions
|
|
@ -67,6 +67,7 @@ already used which is string literal notation:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
char word[] = "Hello";
|
char word[] = "Hello";
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The null terminator is implied in this form, you do not need to add it manually.
|
The null terminator is implied in this form, you do not need to add it manually.
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,8 @@ print(p1.name)
|
||||||
|
|
||||||
Key points to note:
|
Key points to note:
|
||||||
|
|
||||||
- The `__init__` method is the constructor function. You only need to provide it
|
- The `__init__` method is the constructor function and must exist on every
|
||||||
if you are defining properties at instantiation. If it's going to be empty,
|
class to define the properties of the class
|
||||||
don't bother.
|
|
||||||
- `self` is a reference to the class itself and the object it will create, akin
|
- `self` is a reference to the class itself and the object it will create, akin
|
||||||
to `this` in other languages
|
to `this` in other languages
|
||||||
- You must pass `self` as a parameter to every method (this is a difference from
|
- You must pass `self` as a parameter to every method (this is a difference from
|
||||||
|
|
@ -107,32 +106,6 @@ class Person:
|
||||||
return self.age < 20
|
return self.age < 20
|
||||||
```
|
```
|
||||||
|
|
||||||
## Inheritance
|
|
||||||
|
|
||||||
Say that `TableService` is a child of `SqliteService`:
|
|
||||||
|
|
||||||
```py
|
|
||||||
class TableService(SqliteService):
|
|
||||||
```
|
|
||||||
|
|
||||||
Say that the parent does something in the constructor, that you want to also do
|
|
||||||
in the child, or if you want to change the parent constuctor behaviour, you have
|
|
||||||
to invoke `super`:
|
|
||||||
|
|
||||||
```py
|
|
||||||
class SqliteService:
|
|
||||||
def __init__(self, db_connection):
|
|
||||||
self.connection = db_connection
|
|
||||||
self.cursor = db_connection.cursor()
|
|
||||||
|
|
||||||
class TableService(SqliteService):
|
|
||||||
def __init__(self, db_connection):
|
|
||||||
super().__init__(db_connection)
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
See more in [Class inheritance in Python](./Class_inheritance_in_Python.md).
|
|
||||||
|
|
||||||
## Object references
|
## Object references
|
||||||
|
|
||||||
When you log a class you get a reference to its hexadecimal memory reference.
|
When you log a class you get a reference to its hexadecimal memory reference.
|
||||||
|
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
---
|
|
||||||
tags:
|
|
||||||
- C
|
|
||||||
---
|
|
||||||
|
|
||||||
## What type is a function?
|
|
||||||
|
|
||||||
A function does not have to a dedicated primitive type. It is a **derived**
|
|
||||||
type, meaning that its type-signature comes from the primitive types that it
|
|
||||||
uses.
|
|
||||||
|
|
||||||
On this basis, a function type is derived from its return type and the number
|
|
||||||
and types of its parameters.
|
|
||||||
|
|
||||||
E.g. for the function:
|
|
||||||
|
|
||||||
```c
|
|
||||||
int mimic_number(int num) {
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
It's type is a product of:
|
|
||||||
|
|
||||||
- its return type (`int`)
|
|
||||||
- the number of parameters (`1`)
|
|
||||||
- the type of its parameter (`int`)
|
|
||||||
|
|
||||||
## Function declarators and function definitions
|
|
||||||
|
|
||||||
In C, it is possible to declare a function without specifying the body, e.g:
|
|
||||||
|
|
||||||
```c
|
|
||||||
int f(void);
|
|
||||||
void g(int i, int j);
|
|
||||||
```
|
|
||||||
|
|
||||||
Are all examples of function declarators.
|
|
||||||
|
|
||||||
Later then you can go back and provide the definition. Note that this is just
|
|
||||||
the same as a normal full function declaration, it's just you've previously
|
|
||||||
declared its existence:
|
|
||||||
|
|
||||||
```c
|
|
||||||
|
|
||||||
int f(void);
|
|
||||||
|
|
||||||
// Some other code
|
|
||||||
|
|
||||||
int f(void) {
|
|
||||||
printf("Here's the definition.")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### What's the point of this?
|
|
||||||
|
|
||||||
The only real utility in distinguishing the declaration from the definition is
|
|
||||||
when creating reusable libraries.
|
|
||||||
|
|
||||||
These follow this sequence:
|
|
||||||
|
|
||||||
- define a `.h` header file with function declaration
|
|
||||||
- define a `.c` file with the function definition
|
|
||||||
- import the function into `main.c` and call function
|
|
||||||
|
|
||||||
Applied example:
|
|
||||||
|
|
||||||
```c
|
|
||||||
// math_utils.h
|
|
||||||
|
|
||||||
int add (int a, int b);
|
|
||||||
```
|
|
||||||
|
|
||||||
```c
|
|
||||||
// math_utils.c
|
|
||||||
int add (int a, int b) {
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
And then in `main.c`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include "math_utils.h"
|
|
||||||
|
|
||||||
int main(void):
|
|
||||||
int sum = add(5, 3)
|
|
||||||
```
|
|
||||||
|
|
||||||
> The compiler compiles each .c file separately. The header file tells main.c
|
|
||||||
> that add and multiply exist somewhere, even though they're defined in a
|
|
||||||
> different file. The linker connects everything together at the end.
|
|
||||||
|
|
||||||
In C, the distinction between arguments and parameters is more acute than other
|
|
||||||
languages:
|
|
||||||
Loading…
Add table
Reference in a new issue